diff --git a/.github/actions/setup-repo/action.yml b/.github/actions/setup-repo/action.yml
new file mode 100644
index 0000000..3c5cc7d
--- /dev/null
+++ b/.github/actions/setup-repo/action.yml
@@ -0,0 +1,35 @@
+name: Setup repo
+description: Runs all steps to setup the repo (install node_modules, build, etc...)
+inputs:
+ registry-token:
+ description: 'PAT to access registries'
+runs:
+ using: 'composite'
+ steps:
+ - name: Get yarn cache directory path
+ id: yarn-cache-dir-path
+ shell: bash
+ run: |
+ echo "::set-output name=dir::$(yarn cache dir)"
+ echo "::set-output name=version::$(yarn -v)"
+
+ - uses: actions/setup-node@v3
+ with:
+ node-version: '20'
+
+ - uses: actions/cache@v2
+ id: yarn-cache
+ with:
+ path: |
+ **/node_modules
+ ${{ steps.yarn-cache-dir-path.outputs.dir }}
+
+ key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-yarn-
+
+ - name: Install dependencies
+ shell: bash
+ run: echo "//npm.pkg.github.com/:_authToken=$GH_REGISTRY_ACCESS_TOKEN" >> .npmrc && yarn install --frozen-lockfile --verbose && rm -f .npmrc
+ env:
+ GH_REGISTRY_ACCESS_TOKEN: ${{ inputs.registry-token }}
\ No newline at end of file
diff --git a/.github/workflows/ci-deep.yml b/.github/workflows/ci-deep.yml
index a75ce1b..f0539f8 100644
--- a/.github/workflows/ci-deep.yml
+++ b/.github/workflows/ci-deep.yml
@@ -32,8 +32,10 @@ jobs:
node-version: 18
cache: "yarn"
- - name: Install dependencies
- run: yarn install
+ - name: Setup repo
+ uses: ./.github/actions/setup-repo
+ with:
+ registry-token: ${{ secrets.GH_REGISTRY_ACCESS_TOKEN }}
- name: Run solhint
run: yarn lint:check
@@ -56,7 +58,12 @@ jobs:
version: nightly
- name: Compile foundry
- run: yarn compile --sizes
+ run: yarn compile
+
+ - name: Setup repo
+ uses: ./.github/actions/setup-repo
+ with:
+ registry-token: ${{ secrets.GH_REGISTRY_ACCESS_TOKEN }}
- name: "Cache the build so that it can be re-used by the other jobs"
uses: "actions/cache/save@v3"
@@ -65,6 +72,7 @@ jobs:
path: |
cache-forge
out
+ node_modules
- name: "Add build summary"
run: |
@@ -85,6 +93,7 @@ jobs:
path: |
cache-forge
out
+ node_modules
key: "build-${{ github.sha }}"
- name: Install Foundry
@@ -92,6 +101,13 @@ jobs:
with:
version: nightly
+ - uses: actions/setup-python@v5
+ with:
+ python-version: '3.8'
+
+ - name: Install vyper
+ run: pip install vyper==0.2.16
+
- name: Run Foundry tests
run: yarn test:unit
env:
@@ -119,6 +135,7 @@ jobs:
path: |
cache-forge
out
+ node_modules
key: "build-${{ github.sha }}"
- name: Install Foundry
@@ -126,6 +143,13 @@ jobs:
with:
version: nightly
+ - uses: actions/setup-python@v5
+ with:
+ python-version: '3.8'
+
+ - name: Install vyper
+ run: pip install vyper==0.2.16
+
- name: Run Foundry tests
run: yarn test:invariant
env:
@@ -155,6 +179,7 @@ jobs:
path: |
cache-forge
out
+ node_modules
key: "build-${{ github.sha }}"
- name: Install Foundry
@@ -162,6 +187,13 @@ jobs:
with:
version: nightly
+ - uses: actions/setup-python@v5
+ with:
+ python-version: '3.8'
+
+ - name: Install vyper
+ run: pip install vyper==0.2.16
+
- name: Run Foundry tests
run: yarn test:fuzz
env:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 20fef55..e83e289 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -21,8 +21,10 @@ jobs:
node-version: 18
cache: "yarn"
- - name: Install dependencies
- run: yarn install
+ - name: Setup repo
+ uses: ./.github/actions/setup-repo
+ with:
+ registry-token: ${{ secrets.GH_REGISTRY_ACCESS_TOKEN }}
- name: Run solhint
run: yarn lint:check
@@ -44,8 +46,13 @@ jobs:
with:
version: nightly
+ - name: Setup repo
+ uses: ./.github/actions/setup-repo
+ with:
+ registry-token: ${{ secrets.GH_REGISTRY_ACCESS_TOKEN }}
+
- name: Compile foundry
- run: yarn compile --sizes
+ run: yarn compile
- name: "Cache the build so that it can be re-used by the other jobs"
uses: "actions/cache/save@v3"
@@ -54,6 +61,7 @@ jobs:
path: |
cache-forge
out
+ node_modules
- name: "Add build summary"
run: |
@@ -74,6 +82,7 @@ jobs:
path: |
cache-forge
out
+ node_modules
key: "build-${{ github.sha }}"
- name: Install Foundry
@@ -81,6 +90,13 @@ jobs:
with:
version: nightly
+ - uses: actions/setup-python@v5
+ with:
+ python-version: '3.8'
+
+ - name: Install vyper
+ run: pip install vyper==0.2.16
+
- name: Run Foundry tests
run: yarn test:unit
env:
@@ -108,6 +124,7 @@ jobs:
path: |
cache-forge
out
+ node_modules
key: "build-${{ github.sha }}"
- name: Install Foundry
@@ -115,6 +132,13 @@ jobs:
with:
version: nightly
+ - uses: actions/setup-python@v5
+ with:
+ python-version: '3.8'
+
+ - name: Install vyper
+ run: pip install vyper==0.2.16
+
- name: Run Foundry tests
run: yarn test:invariant
env:
@@ -144,6 +168,7 @@ jobs:
path: |
cache-forge
out
+ node_modules
key: "build-${{ github.sha }}"
- name: Install Foundry
@@ -151,6 +176,13 @@ jobs:
with:
version: nightly
+ - uses: actions/setup-python@v5
+ with:
+ python-version: '3.8'
+
+ - name: Install vyper
+ run: pip install vyper==0.2.16
+
- name: Run Foundry tests
run: npm run test:fuzz
env:
@@ -176,6 +208,18 @@ jobs:
- name: "Install Foundry"
uses: "foundry-rs/foundry-toolchain@v1"
+ - name: Setup repo
+ uses: ./.github/actions/setup-repo
+ with:
+ registry-token: ${{ secrets.GH_REGISTRY_ACCESS_TOKEN }}
+
+ - uses: actions/setup-python@v5
+ with:
+ python-version: '3.8'
+
+ - name: Install vyper
+ run: pip install vyper==0.2.16
+
- name: "Install lcov"
run: "sudo apt-get install lcov"
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 0000000..af66bba
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+@angleprotocol:registry=https://npm.pkg.github.com
diff --git a/.solhint.json b/.solhint.json
index 99c3260..d9609eb 100644
--- a/.solhint.json
+++ b/.solhint.json
@@ -2,7 +2,7 @@
"extends": "solhint:recommended",
"plugins": ["prettier"],
"rules": {
- "max-line-length": ["error", 120],
+ "max-line-length": ["warn", 120],
"avoid-call-value": "warn",
"avoid-low-level-calls": "off",
"avoid-tx-origin": "warn",
@@ -23,6 +23,7 @@
"no-complex-fallback": "off",
"reason-string": "off",
"func-visibility": ["warn", { "ignoreConstructors": true }],
- "explicit-types": ["error","explicit"]
+ "explicit-types": ["error","explicit"],
+ "custom-errors": "off"
}
}
diff --git a/.vscode/settings.json b/.vscode/settings.json
index e6b354a..ab5d1b9 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,5 +1,5 @@
{
- "solidity.compileUsingRemoteVersion": "0.8.20",
+ "solidity.compileUsingRemoteVersion": "0.8.22",
"[solidity]": {
"editor.defaultFormatter": "JuanBlanco.solidity",
"editor.formatOnSave": true
diff --git a/README.md b/README.md
index 07aa577..d5a8393 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,10 @@
# Angle DAO
[![CI](https://github.com/AngleProtocol/boilerplate/actions/workflows/ci.yml/badge.svg)](https://github.com/AngleProtocol/boilerplate/actions)
-[![Coverage](https://codecov.io/gh/AngleProtocol/boilerplate/branch/main/graph/badge.svg)](https://codecov.io/gh/AngleProtocol/boilerplate)
-This repository proposes a template that is based on foundry frameworks. It also provides templates for EVM compatible smart contracts (in `./contracts/example`), tests and deployment scripts.
+## Overview
+
+This repository contains all the contracts related to the Angle DAO including the angle, veANGLE ... etc.
## Starting
@@ -119,32 +120,6 @@ yarn hardhat:coverage
yarn foundry:coverage
```
-### Simulate
-
-You can simulate your transaction live or in fork mode. For both option you need to
-complete the `scripts/foundry/Simulate.s.sol` with your values: address sending the tx,
-address caled and the data to give to this address call.
-
-For live simulation
-
-```bash
-yarn foundry:simulate
-```
-
-For fork simulation
-
-```bash
-yarn foundry:fork
-yarn foundry:simulate:fork
-```
-
-For fork simulation at a given block
-
-```bash
-yarn foundry:fork:block ${XXXX}
-yarn foundry:simulate:fork
-```
-
### Gas report
```bash
diff --git a/contracts/dao/veANGLE-old.vy b/contracts/dao/veANGLE-old.vy
new file mode 100644
index 0000000..674f991
--- /dev/null
+++ b/contracts/dao/veANGLE-old.vy
@@ -0,0 +1,710 @@
+# @version 0.2.16
+"""
+@title Voting Escrow
+@author Angle Protocol
+@license MIT
+@notice Votes have a weight depending on time, so that users are
+ committed to the future of (whatever they are voting for)
+@dev Vote weight decays linearly over time. Lock time cannot be
+ more than `MAXTIME` (4 years).
+"""
+
+# Original idea and credit:
+# Curve Finance's veCRV
+# https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy
+# veANGLE is a fork with only one view functions added to it to make veANGLE compatible
+# with Compound governance system. The references to the controller have also been removed
+
+# Voting escrow to have time-weighted votes
+# Votes have a weight depending on time, so that users are committed
+# to the future of (whatever they are voting for).
+# The weight in this implementation is linear, and lock cannot be more than maxtime:
+# w ^
+# 1 + /
+# | /
+# | /
+# | /
+# |/
+# 0 +--------+------> time
+# maxtime (4 years?)
+
+struct Point:
+ bias: int128
+ slope: int128 # - dweight / dt
+ ts: uint256
+ blk: uint256 # block
+# We cannot really do block numbers per se b/c slope is per time, not per block
+# and per block could be fairly bad b/c Ethereum changes blocktimes.
+# What we can do is to extrapolate ***At functions
+
+struct LockedBalance:
+ amount: int128
+ end: uint256
+
+
+interface ERC20:
+ def decimals() -> uint256: view
+ def name() -> String[64]: view
+ def symbol() -> String[32]: view
+ def transfer(to: address, amount: uint256) -> bool: nonpayable
+ def transferFrom(spender: address, to: address, amount: uint256) -> bool: nonpayable
+
+
+# Interface for checking whether address belongs to a whitelisted
+# type of a smart wallet.
+# When new types are added - the whole contract is changed
+# The check() method is modifying to be able to use caching
+# for individual wallet addresses
+interface SmartWalletChecker:
+ def check(addr: address) -> bool: nonpayable
+
+DEPOSIT_FOR_TYPE: constant(int128) = 0
+CREATE_LOCK_TYPE: constant(int128) = 1
+INCREASE_LOCK_AMOUNT: constant(int128) = 2
+INCREASE_UNLOCK_TIME: constant(int128) = 3
+
+
+event CommitOwnership:
+ admin: address
+
+event ApplyOwnership:
+ admin: address
+
+event Deposit:
+ provider: indexed(address)
+ value: uint256
+ locktime: indexed(uint256)
+ type: int128
+ ts: uint256
+
+event Withdraw:
+ provider: indexed(address)
+ value: uint256
+ ts: uint256
+
+event Supply:
+ prevSupply: uint256
+ supply: uint256
+
+
+WEEK: constant(uint256) = 7 * 86400 # all future times are rounded by week
+MAXTIME: constant(uint256) = 4 * 365 * 86400 # 4 years
+MULTIPLIER: constant(uint256) = 10 ** 18
+
+token: public(address)
+supply: public(uint256)
+
+locked: public(HashMap[address, LockedBalance])
+
+epoch: public(uint256)
+point_history: public(Point[100000000000000000000000000000]) # epoch -> unsigned point
+user_point_history: public(HashMap[address, Point[1000000000]]) # user -> Point[user_epoch]
+user_point_epoch: public(HashMap[address, uint256])
+slope_changes: public(HashMap[uint256, int128]) # time -> signed slope change
+
+name: public(String[64])
+symbol: public(String[32])
+decimals: public(uint256)
+
+# Checker for whitelisted (smart contract) wallets which are allowed to deposit
+# The goal is to prevent tokenizing the escrow
+future_smart_wallet_checker: public(address)
+smart_wallet_checker: public(address)
+
+admin: public(address) # Can and will be a smart contract
+future_admin: public(address)
+
+initialized: public(bool)
+
+
+@external
+def __init__():
+ """
+ @notice Contract constructor
+ @dev The contract has an initializer to prevent the take over of the implementation
+ """
+ assert self.initialized == False #dev: contract is already initialized
+ self.initialized = True
+
+@external
+def initialize(_admin: address, token_addr: address, _smart_wallet_checker: address, _name: String[64], _symbol: String[32]):
+ """
+ @notice Contract initializer
+ @param _admin Future veANGLE admin
+ @param token_addr `ERC20ANGLE` token address
+ @param _smart_wallet_checker Future smart wallet checker contract
+ @param _name Token name
+ @param _symbol Token symbol
+ """
+ assert self.initialized == False #dev: contract is already initialized
+ self.initialized = True
+ assert _admin!= ZERO_ADDRESS #dev: admin cannot be the 0 address
+ self.admin = _admin
+ self.token = token_addr
+ self.smart_wallet_checker = _smart_wallet_checker
+ self.point_history[0].blk = block.number
+ self.point_history[0].ts = block.timestamp
+
+ _decimals: uint256 = ERC20(token_addr).decimals()
+ assert _decimals <= 255
+ self.decimals = _decimals
+
+ self.name = _name
+ self.symbol = _symbol
+
+
+@external
+def commit_transfer_ownership(addr: address):
+ """
+ @notice Transfer ownership of VotingEscrow contract to `addr`
+ @param addr Address to have ownership transferred to
+ """
+ assert msg.sender == self.admin # dev: admin only
+ assert addr != ZERO_ADDRESS # dev: future admin cannot be the 0 address
+ self.future_admin = addr
+ log CommitOwnership(addr)
+
+@external
+def accept_transfer_ownership():
+ """
+ @notice Accept a pending ownership transfer
+ """
+ _admin: address = self.future_admin
+ assert msg.sender == _admin # dev: future admin only
+
+ self.admin = _admin
+ log ApplyOwnership(_admin)
+
+@external
+def apply_transfer_ownership():
+ """
+ @notice Apply ownership transfer
+ """
+ assert msg.sender == self.admin # dev: admin only
+ _admin: address = self.future_admin
+ assert _admin != ZERO_ADDRESS # dev: admin not set
+ self.admin = _admin
+ log ApplyOwnership(_admin)
+
+
+@external
+def commit_smart_wallet_checker(addr: address):
+ """
+ @notice Set an external contract to check for approved smart contract wallets
+ @param addr Address of Smart contract checker
+ """
+ assert msg.sender == self.admin
+ self.future_smart_wallet_checker = addr
+
+
+@external
+def apply_smart_wallet_checker():
+ """
+ @notice Apply setting external contract to check approved smart contract wallets
+ """
+ assert msg.sender == self.admin
+ self.smart_wallet_checker = self.future_smart_wallet_checker
+
+
+@internal
+def assert_not_contract(addr: address):
+ """
+ @notice Check if the call is from a whitelisted smart contract, revert if not
+ @param addr Address to be checked
+ """
+ if addr != tx.origin:
+ checker: address = self.smart_wallet_checker
+ if checker != ZERO_ADDRESS:
+ if SmartWalletChecker(checker).check(addr):
+ return
+ raise "Smart contract depositors not allowed"
+
+
+@external
+@view
+def get_last_user_slope(addr: address) -> int128:
+ """
+ @notice Get the most recently recorded rate of voting power decrease for `addr`
+ @param addr Address of the user wallet
+ @return Value of the slope
+ """
+ uepoch: uint256 = self.user_point_epoch[addr]
+ return self.user_point_history[addr][uepoch].slope
+
+
+@external
+@view
+def user_point_history__ts(_addr: address, _idx: uint256) -> uint256:
+ """
+ @notice Get the timestamp for checkpoint `_idx` for `_addr`
+ @param _addr User wallet address
+ @param _idx User epoch number
+ @return Epoch time of the checkpoint
+ """
+ return self.user_point_history[_addr][_idx].ts
+
+
+@external
+@view
+def locked__end(_addr: address) -> uint256:
+ """
+ @notice Get timestamp when `_addr`'s lock finishes
+ @param _addr User wallet
+ @return Epoch time of the lock end
+ """
+ return self.locked[_addr].end
+
+
+@internal
+def _checkpoint(addr: address, old_locked: LockedBalance, new_locked: LockedBalance):
+ """
+ @notice Record global and per-user data to checkpoint
+ @param addr User's wallet address. No user checkpoint if 0x0
+ @param old_locked Pevious locked amount / end lock time for the user
+ @param new_locked New locked amount / end lock time for the user
+ """
+ u_old: Point = empty(Point)
+ u_new: Point = empty(Point)
+ old_dslope: int128 = 0
+ new_dslope: int128 = 0
+ _epoch: uint256 = self.epoch
+
+ if addr != ZERO_ADDRESS:
+ # Calculate slopes and biases
+ # Kept at zero when they have to
+ if old_locked.end > block.timestamp and old_locked.amount > 0:
+ u_old.slope = old_locked.amount / MAXTIME
+ u_old.bias = u_old.slope * convert(old_locked.end - block.timestamp, int128)
+ if new_locked.end > block.timestamp and new_locked.amount > 0:
+ u_new.slope = new_locked.amount / MAXTIME
+ u_new.bias = u_new.slope * convert(new_locked.end - block.timestamp, int128)
+
+ # Read values of scheduled changes in the slope
+ # old_locked.end can be in the past and in the future
+ # new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros
+ old_dslope = self.slope_changes[old_locked.end]
+ if new_locked.end != 0:
+ if new_locked.end == old_locked.end:
+ new_dslope = old_dslope
+ else:
+ new_dslope = self.slope_changes[new_locked.end]
+
+ last_point: Point = Point({bias: 0, slope: 0, ts: block.timestamp, blk: block.number})
+ if _epoch > 0:
+ last_point = self.point_history[_epoch]
+ last_checkpoint: uint256 = last_point.ts
+ # initial_last_point is used for extrapolation to calculate block number
+ # (approximately, for *At methods) and save them
+ # as we cannot figure that out exactly from inside the contract
+ initial_last_point: Point = last_point
+ block_slope: uint256 = 0 # dblock/dt
+ if block.timestamp > last_point.ts:
+ block_slope = MULTIPLIER * (block.number - last_point.blk) / (block.timestamp - last_point.ts)
+ # If last point is already recorded in this block, slope=0
+ # But that's ok b/c we know the block in such case
+
+ # Go over weeks to fill history and calculate what the current point is
+ t_i: uint256 = (last_checkpoint / WEEK) * WEEK
+ for i in range(255):
+ # Hopefully it won't happen that this won't get used in 5 years!
+ # If it does, users will be able to withdraw but vote weight will be broken
+ t_i += WEEK
+ d_slope: int128 = 0
+ if t_i > block.timestamp:
+ t_i = block.timestamp
+ else:
+ d_slope = self.slope_changes[t_i]
+ last_point.bias -= last_point.slope * convert(t_i - last_checkpoint, int128)
+ last_point.slope += d_slope
+ if last_point.bias < 0: # This can happen
+ last_point.bias = 0
+ if last_point.slope < 0: # This cannot happen - just in case
+ last_point.slope = 0
+ last_checkpoint = t_i
+ last_point.ts = t_i
+ last_point.blk = initial_last_point.blk + block_slope * (t_i - initial_last_point.ts) / MULTIPLIER
+ _epoch += 1
+ if t_i == block.timestamp:
+ last_point.blk = block.number
+ break
+ else:
+ self.point_history[_epoch] = last_point
+
+ self.epoch = _epoch
+ # Now point_history is filled until t=now
+
+ if addr != ZERO_ADDRESS:
+ # If last point was in this block, the slope change has been applied already
+ # But in such case we have 0 slope(s)
+ last_point.slope += (u_new.slope - u_old.slope)
+ last_point.bias += (u_new.bias - u_old.bias)
+ if last_point.slope < 0:
+ last_point.slope = 0
+ if last_point.bias < 0:
+ last_point.bias = 0
+
+ # Record the changed point into history
+ self.point_history[_epoch] = last_point
+
+ if addr != ZERO_ADDRESS:
+ # Schedule the slope changes (slope is going down)
+ # We subtract new_user_slope from [new_locked.end]
+ # and add old_user_slope to [old_locked.end]
+ if old_locked.end > block.timestamp:
+ # old_dslope was - u_old.slope, so we cancel that
+ old_dslope += u_old.slope
+ if new_locked.end == old_locked.end:
+ old_dslope -= u_new.slope # It was a new deposit, not extension
+ self.slope_changes[old_locked.end] = old_dslope
+
+ if new_locked.end > block.timestamp:
+ if new_locked.end > old_locked.end:
+ new_dslope -= u_new.slope # old slope disappeared at this point
+ self.slope_changes[new_locked.end] = new_dslope
+ # else: we recorded it already in old_dslope
+
+ # Now handle user history
+ user_epoch: uint256 = self.user_point_epoch[addr] + 1
+
+ self.user_point_epoch[addr] = user_epoch
+ u_new.ts = block.timestamp
+ u_new.blk = block.number
+ self.user_point_history[addr][user_epoch] = u_new
+
+
+@internal
+def _deposit_for(_addr: address, _value: uint256, unlock_time: uint256, locked_balance: LockedBalance, type: int128, sender: address):
+ """
+ @notice Deposit and lock tokens for a user
+ @param _addr User's wallet address
+ @param _value Amount to deposit
+ @param unlock_time New time when to unlock the tokens, or 0 if unchanged
+ @param locked_balance Previous locked amount / timestamp
+ """
+ _locked: LockedBalance = locked_balance
+ supply_before: uint256 = self.supply
+
+ self.supply = supply_before + _value
+ old_locked: LockedBalance = _locked
+ # Adding to existing lock, or if a lock is expired - creating a new one
+ _locked.amount += convert(_value, int128)
+ if unlock_time != 0:
+ _locked.end = unlock_time
+ self.locked[_addr] = _locked
+
+ # Possibilities:
+ # Both old_locked.end could be current or expired (>/< block.timestamp)
+ # value == 0 (extend lock) or value > 0 (add to lock or extend lock)
+ # _locked.end > block.timestamp (always)
+ self._checkpoint(_addr, old_locked, _locked)
+
+ if _value != 0:
+ assert ERC20(self.token).transferFrom(sender, self, _value)
+
+ log Deposit(_addr, _value, _locked.end, type, block.timestamp)
+ log Supply(supply_before, supply_before + _value)
+
+
+@external
+def checkpoint():
+ """
+ @notice Record global data to checkpoint
+ """
+ self._checkpoint(ZERO_ADDRESS, empty(LockedBalance), empty(LockedBalance))
+
+
+@external
+@nonreentrant('lock')
+def deposit_for(_addr: address, _value: uint256):
+ """
+ @notice Deposit `_value` tokens for `_addr` and add to the lock
+ @dev Anyone (even a smart contract) can deposit for someone else, but
+ cannot extend their locktime and deposit for a brand new user
+ @param _addr User's wallet address
+ @param _value Amount to add to user's lock
+ """
+ _locked: LockedBalance = self.locked[_addr]
+
+ assert _value > 0 # dev: need non-zero value
+ assert _locked.amount > 0, "No existing lock found"
+ assert _locked.end > block.timestamp, "Cannot add to expired lock. Withdraw"
+
+ self._deposit_for(_addr, _value, 0, self.locked[_addr], DEPOSIT_FOR_TYPE, msg.sender)
+
+
+@external
+@nonreentrant('lock')
+def create_lock(_value: uint256, _unlock_time: uint256):
+ """
+ @notice Deposit `_value` tokens for `msg.sender` and lock until `_unlock_time`
+ @param _value Amount to deposit
+ @param _unlock_time Epoch time when tokens unlock, rounded down to whole weeks
+ """
+ self.assert_not_contract(msg.sender)
+ unlock_time: uint256 = (_unlock_time / WEEK) * WEEK # Locktime is rounded down to weeks
+ _locked: LockedBalance = self.locked[msg.sender]
+
+ assert _value > 0 # dev: need non-zero value
+ assert _locked.amount == 0, "Withdraw old tokens first"
+ assert unlock_time > block.timestamp, "Can only lock until time in the future"
+ assert unlock_time <= block.timestamp + MAXTIME, "Voting lock can be 4 years max"
+
+ self._deposit_for(msg.sender, _value, unlock_time, _locked, CREATE_LOCK_TYPE, msg.sender)
+
+
+@external
+@nonreentrant('lock')
+def increase_amount(_value: uint256):
+ """
+ @notice Deposit `_value` additional tokens for `msg.sender`
+ without modifying the unlock time
+ @param _value Amount of tokens to deposit and add to the lock
+ """
+ self.assert_not_contract(msg.sender)
+ _locked: LockedBalance = self.locked[msg.sender]
+
+ assert _value > 0 # dev: need non-zero value
+ assert _locked.amount > 0, "No existing lock found"
+ assert _locked.end > block.timestamp, "Cannot add to expired lock. Withdraw"
+
+ self._deposit_for(msg.sender, _value, 0, _locked, INCREASE_LOCK_AMOUNT, msg.sender)
+
+
+@external
+@nonreentrant('lock')
+def increase_unlock_time(_unlock_time: uint256):
+ """
+ @notice Extend the unlock time for `msg.sender` to `_unlock_time`
+ @param _unlock_time New epoch time for unlocking
+ """
+ self.assert_not_contract(msg.sender)
+ _locked: LockedBalance = self.locked[msg.sender]
+ unlock_time: uint256 = (_unlock_time / WEEK) * WEEK # Locktime is rounded down to weeks
+
+ assert _locked.end > block.timestamp, "Lock expired"
+ assert _locked.amount > 0, "Nothing is locked"
+ assert unlock_time > _locked.end, "Can only increase lock duration"
+ assert unlock_time <= block.timestamp + MAXTIME, "Voting lock can be 4 years max"
+
+ self._deposit_for(msg.sender, 0, unlock_time, _locked, INCREASE_UNLOCK_TIME, msg.sender)
+
+
+@external
+@nonreentrant('lock')
+def withdraw():
+ """
+ @notice Withdraw all tokens for `msg.sender`
+ @dev Only possible if the lock has expired
+ """
+ _locked: LockedBalance = self.locked[msg.sender]
+ assert block.timestamp >= _locked.end, "The lock didn't expire"
+ value: uint256 = convert(_locked.amount, uint256)
+
+ old_locked: LockedBalance = _locked
+ _locked.end = 0
+ _locked.amount = 0
+ self.locked[msg.sender] = _locked
+ supply_before: uint256 = self.supply
+ self.supply = supply_before - value
+
+ # old_locked can have either expired <= timestamp or zero end
+ # _locked has only 0 end
+ # Both can have >= 0 amount
+ self._checkpoint(msg.sender, old_locked, _locked)
+
+ assert ERC20(self.token).transfer(msg.sender, value)
+
+ log Withdraw(msg.sender, value, block.timestamp)
+ log Supply(supply_before, supply_before - value)
+
+
+# The following ERC20/minime-compatible methods are not real balanceOf and supply!
+# They measure the weights for the purpose of voting, so they don't represent
+# real coins.
+
+@internal
+@view
+def find_block_epoch(_block: uint256, max_epoch: uint256) -> uint256:
+ """
+ @notice Binary search to estimate timestamp for block number
+ @param _block Block to find
+ @param max_epoch Don't go beyond this epoch
+ @return Approximate timestamp for block
+ """
+ # Binary search
+ _min: uint256 = 0
+ _max: uint256 = max_epoch
+ for i in range(128): # Will be always enough for 128-bit numbers
+ if _min >= _max:
+ break
+ _mid: uint256 = (_min + _max + 1) / 2
+ if self.point_history[_mid].blk <= _block:
+ _min = _mid
+ else:
+ _max = _mid - 1
+ return _min
+
+
+@external
+@view
+def balanceOf(addr: address, _t: uint256 = block.timestamp) -> uint256:
+ """
+ @notice Get the current voting power for `msg.sender`
+ @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility
+ @param addr User wallet address
+ @param _t Epoch time to return voting power at
+ @return User voting power
+ """
+ _epoch: uint256 = self.user_point_epoch[addr]
+ if _epoch == 0:
+ return 0
+ else:
+ last_point: Point = self.user_point_history[addr][_epoch]
+ last_point.bias -= last_point.slope * convert(_t - last_point.ts, int128)
+ if last_point.bias < 0:
+ last_point.bias = 0
+ return convert(last_point.bias, uint256)
+
+
+@internal
+@view
+def _balanceOfAt(addr: address, _block: uint256) -> uint256:
+ """
+ @notice measure voting power of `addr` at block height `_block`
+ @param addr User's wallet address
+ @param _block Block to calculate the voting power at
+ @return Voting power
+ """
+ # Copying and pasting totalSupply code because Vyper cannot pass by
+ # reference yet
+ assert _block <= block.number
+
+ # Binary search
+ _min: uint256 = 0
+ _max: uint256 = self.user_point_epoch[addr]
+ for i in range(128): # Will be always enough for 128-bit numbers
+ if _min >= _max:
+ break
+ _mid: uint256 = (_min + _max + 1) / 2
+ if self.user_point_history[addr][_mid].blk <= _block:
+ _min = _mid
+ else:
+ _max = _mid - 1
+
+ upoint: Point = self.user_point_history[addr][_min]
+
+ max_epoch: uint256 = self.epoch
+ _epoch: uint256 = self.find_block_epoch(_block, max_epoch)
+ point_0: Point = self.point_history[_epoch]
+ d_block: uint256 = 0
+ d_t: uint256 = 0
+ if _epoch < max_epoch:
+ point_1: Point = self.point_history[_epoch + 1]
+ d_block = point_1.blk - point_0.blk
+ d_t = point_1.ts - point_0.ts
+ else:
+ d_block = block.number - point_0.blk
+ d_t = block.timestamp - point_0.ts
+ block_time: uint256 = point_0.ts
+ if d_block != 0:
+ block_time += d_t * (_block - point_0.blk) / d_block
+
+ upoint.bias -= upoint.slope * convert(block_time - upoint.ts, int128)
+ if upoint.bias >= 0:
+ return convert(upoint.bias, uint256)
+ else:
+ return 0
+
+
+@external
+@view
+def balanceOfAt(addr: address, _block: uint256) -> uint256:
+ """
+ @notice Measure voting power of `addr` at block height `_block`
+ @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime
+ @param addr User's wallet address
+ @param _block Block to calculate the voting power at
+ @return Voting power
+ """
+ return self._balanceOfAt(addr,_block)
+
+
+@external
+@view
+def getPastVotes(addr: address, _block: uint256) -> uint256:
+ """
+ @notice Measure voting power of `addr` at block height `_block`
+ @dev Adheres to ERC20Votes `getPastVotes` interface: @openzeppelin-contracts-upgradeable/blob/master/contracts/token/ERC20/extensions/ERC20VotesCompUpgradeable.sol
+ @param addr User's wallet address
+ @param _block Block to calculate the voting power at
+ @return Voting power
+ """
+ return self._balanceOfAt(addr,_block)
+
+
+@internal
+@view
+def supply_at(point: Point, t: uint256) -> uint256:
+ """
+ @notice Calculate total voting power at some point in the past
+ @param point The point (bias/slope) to start search from
+ @param t Time to calculate the total voting power at
+ @return Total voting power at that time
+ """
+ last_point: Point = point
+ t_i: uint256 = (last_point.ts / WEEK) * WEEK
+ for i in range(255):
+ t_i += WEEK
+ d_slope: int128 = 0
+ if t_i > t:
+ t_i = t
+ else:
+ d_slope = self.slope_changes[t_i]
+ last_point.bias -= last_point.slope * convert(t_i - last_point.ts, int128)
+ if t_i == t:
+ break
+ last_point.slope += d_slope
+ last_point.ts = t_i
+
+ if last_point.bias < 0:
+ last_point.bias = 0
+ return convert(last_point.bias, uint256)
+
+
+@external
+@view
+def totalSupply(t: uint256 = block.timestamp) -> uint256:
+ """
+ @notice Calculate total voting power
+ @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility
+ @return Total voting power
+ """
+ _epoch: uint256 = self.epoch
+ last_point: Point = self.point_history[_epoch]
+ return self.supply_at(last_point, t)
+
+
+@external
+@view
+def totalSupplyAt(_block: uint256) -> uint256:
+ """
+ @notice Calculate total voting power at some point in the past
+ @param _block Block to calculate the total voting power at
+ @return Total voting power at `_block`
+ """
+ assert _block <= block.number
+ _epoch: uint256 = self.epoch
+ target_epoch: uint256 = self.find_block_epoch(_block, _epoch)
+
+ point: Point = self.point_history[target_epoch]
+ dt: uint256 = 0
+ if target_epoch < _epoch:
+ point_next: Point = self.point_history[target_epoch + 1]
+ if point.blk != point_next.blk:
+ dt = (_block - point.blk) * (point_next.ts - point.ts) / (point_next.blk - point.blk)
+ else:
+ if point.blk != block.number:
+ dt = (_block - point.blk) * (block.timestamp - point.ts) / (block.number - point.blk)
+ # Now dt contains info on how far are we beyond point
+
+ return self.supply_at(point, point.ts + dt)
\ No newline at end of file
diff --git a/contracts/dao/veANGLE.vy b/contracts/dao/veANGLE.vy
index 674f991..425893b 100644
--- a/contracts/dao/veANGLE.vy
+++ b/contracts/dao/veANGLE.vy
@@ -116,15 +116,7 @@ future_admin: public(address)
initialized: public(bool)
-
-@external
-def __init__():
- """
- @notice Contract constructor
- @dev The contract has an initializer to prevent the take over of the implementation
- """
- assert self.initialized == False #dev: contract is already initialized
- self.initialized = True
+emergency_withdrawal: public(bool)
@external
def initialize(_admin: address, token_addr: address, _smart_wallet_checker: address, _name: String[64], _symbol: String[32]):
@@ -186,6 +178,28 @@ def apply_transfer_ownership():
self.admin = _admin
log ApplyOwnership(_admin)
+@external
+def set_emergency_withdrawal():
+ assert msg.sender == self.admin
+ self.emergency_withdrawal = True
+
+@external
+def withdraw_fast():
+ """
+ @notice withdraw all tokens when in emergency states
+ """
+ assert self.emergency_withdrawal, "Emergency withdrawal not enabled"
+
+ _locked: LockedBalance = self.locked[msg.sender]
+ value: uint256 = convert(_locked.amount, uint256)
+
+ # remove lock
+ self.locked[msg.sender].end = 0
+ self.locked[msg.sender].amount = 0
+
+ assert ERC20(self.token).transfer(msg.sender, value)
+
+ log Withdraw(msg.sender, value, block.timestamp)
@external
def commit_smart_wallet_checker(addr: address):
@@ -371,7 +385,6 @@ def _checkpoint(addr: address, old_locked: LockedBalance, new_locked: LockedBala
u_new.blk = block.number
self.user_point_history[addr][user_epoch] = u_new
-
@internal
def _deposit_for(_addr: address, _value: uint256, unlock_time: uint256, locked_balance: LockedBalance, type: int128, sender: address):
"""
@@ -410,9 +423,9 @@ def checkpoint():
"""
@notice Record global data to checkpoint
"""
+ assert not self.emergency_withdrawal, "Emergency withdrawal enabled"
self._checkpoint(ZERO_ADDRESS, empty(LockedBalance), empty(LockedBalance))
-
@external
@nonreentrant('lock')
def deposit_for(_addr: address, _value: uint256):
@@ -423,6 +436,7 @@ def deposit_for(_addr: address, _value: uint256):
@param _addr User's wallet address
@param _value Amount to add to user's lock
"""
+ assert not self.emergency_withdrawal, "Emergency withdrawal enabled"
_locked: LockedBalance = self.locked[_addr]
assert _value > 0 # dev: need non-zero value
@@ -431,7 +445,6 @@ def deposit_for(_addr: address, _value: uint256):
self._deposit_for(_addr, _value, 0, self.locked[_addr], DEPOSIT_FOR_TYPE, msg.sender)
-
@external
@nonreentrant('lock')
def create_lock(_value: uint256, _unlock_time: uint256):
@@ -440,6 +453,7 @@ def create_lock(_value: uint256, _unlock_time: uint256):
@param _value Amount to deposit
@param _unlock_time Epoch time when tokens unlock, rounded down to whole weeks
"""
+ assert not self.emergency_withdrawal, "Emergency withdrawal enabled"
self.assert_not_contract(msg.sender)
unlock_time: uint256 = (_unlock_time / WEEK) * WEEK # Locktime is rounded down to weeks
_locked: LockedBalance = self.locked[msg.sender]
@@ -460,6 +474,7 @@ def increase_amount(_value: uint256):
without modifying the unlock time
@param _value Amount of tokens to deposit and add to the lock
"""
+ assert not self.emergency_withdrawal, "Emergency withdrawal enabled"
self.assert_not_contract(msg.sender)
_locked: LockedBalance = self.locked[msg.sender]
@@ -477,6 +492,7 @@ def increase_unlock_time(_unlock_time: uint256):
@notice Extend the unlock time for `msg.sender` to `_unlock_time`
@param _unlock_time New epoch time for unlocking
"""
+ assert not self.emergency_withdrawal, "Emergency withdrawal enabled"
self.assert_not_contract(msg.sender)
_locked: LockedBalance = self.locked[msg.sender]
unlock_time: uint256 = (_unlock_time / WEEK) * WEEK # Locktime is rounded down to weeks
@@ -496,6 +512,7 @@ def withdraw():
@notice Withdraw all tokens for `msg.sender`
@dev Only possible if the lock has expired
"""
+ assert not self.emergency_withdrawal, "Emergency withdrawal enabled"
_locked: LockedBalance = self.locked[msg.sender]
assert block.timestamp >= _locked.end, "The lock didn't expire"
value: uint256 = convert(_locked.amount, uint256)
@@ -544,28 +561,59 @@ def find_block_epoch(_block: uint256, max_epoch: uint256) -> uint256:
_max = _mid - 1
return _min
+@internal
+@view
+def _find_user_timestamp_epoch(addr: address, ts: uint256) -> uint256:
+ """
+ @notice Find the epoch for a user's timestamp
+ @param addr User wallet address
+ @param ts Epoch time to find
+ @return User epoch number
+ """
+ minimum_value: uint256 = 0
+ maximum_value: uint256 = self.user_point_epoch[addr]
+
+ for i in range(128): # Will be always enough for 128-bit numbers
+ if minimum_value >= maximum_value:
+ break
+ mid: uint256 = (minimum_value + maximum_value + 1) / 2
+ if self.user_point_history[addr][mid].ts <= ts:
+ minimum_value = mid
+ else:
+ maximum_value = mid - 1
+ return minimum_value
@external
@view
-def balanceOf(addr: address, _t: uint256 = block.timestamp) -> uint256:
+def find_user_timestamp_epoch(addr: address, ts: uint256) -> uint256:
+ """
+ @notice Find the epoch for a user's timestamp
+ @param addr User wallet address
+ @param ts Epoch time to find
+ @return User epoch number
+ """
+ return self._find_user_timestamp_epoch(addr, ts)
+
+@external
+@view
+def balanceOf(addr: address, ts: uint256 = block.timestamp) -> uint256:
"""
@notice Get the current voting power for `msg.sender`
@dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility
@param addr User wallet address
- @param _t Epoch time to return voting power at
+ @param ts Epoch time to return voting power at
@return User voting power
"""
- _epoch: uint256 = self.user_point_epoch[addr]
+ _epoch: uint256 = self._find_user_timestamp_epoch(addr, ts)
if _epoch == 0:
return 0
else:
last_point: Point = self.user_point_history[addr][_epoch]
- last_point.bias -= last_point.slope * convert(_t - last_point.ts, int128)
+ last_point.bias -= last_point.slope * convert(ts - last_point.ts, int128)
if last_point.bias < 0:
last_point.bias = 0
return convert(last_point.bias, uint256)
-
@internal
@view
def _balanceOfAt(addr: address, _block: uint256) -> uint256:
diff --git a/contracts/external/FullMath.sol b/contracts/external/FullMath.sol
index e8cec2c..58b55a8 100644
--- a/contracts/external/FullMath.sol
+++ b/contracts/external/FullMath.sol
@@ -8,105 +8,101 @@ pragma solidity >=0.4.0;
/// @dev This contract was forked from Uniswap V3's contract `FullMath.sol` available here
/// https://github.com/Uniswap/uniswap-v3-core/blob/main/contracts/libraries/FullMath.sol
abstract contract FullMath {
- /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
- /// @param a The multiplicand
- /// @param b The multiplier
- /// @param denominator The divisor
- /// @return result The 256-bit result
- /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv
- /// @dev Contrary to UniswapV3 implementation, this contract doesn't handle `a*b` overflows
- /// and will revert if so
- function _mulDiv(
- uint256 a,
- uint256 b,
- uint256 denominator
- ) internal pure returns (uint256 result) {
- // 512-bit multiply [prod1 prod0] = a * b
- // Compute the product mod 2**256 and mod 2**256 - 1
- // then use the Chinese Remainder Theorem to reconstruct
- // the 512 bit result. The result is stored in two 256
- // variables such that product = prod1 * 2**256 + prod0
- uint256 prod0; // Least significant 256 bits of the product
- uint256 prod1; // Most significant 256 bits of the product
- assembly {
- let mm := mulmod(a, b, not(0))
- prod0 := mul(a, b)
- prod1 := sub(sub(mm, prod0), lt(mm, prod0))
- }
+ /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
+ /// @param a The multiplicand
+ /// @param b The multiplier
+ /// @param denominator The divisor
+ /// @return result The 256-bit result
+ /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv
+ /// @dev Contrary to UniswapV3 implementation, this contract doesn't handle `a*b` overflows
+ /// and will revert if so
+ function _mulDiv(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) {
+ // 512-bit multiply [prod1 prod0] = a * b
+ // Compute the product mod 2**256 and mod 2**256 - 1
+ // then use the Chinese Remainder Theorem to reconstruct
+ // the 512 bit result. The result is stored in two 256
+ // variables such that product = prod1 * 2**256 + prod0
+ uint256 prod0; // Least significant 256 bits of the product
+ uint256 prod1; // Most significant 256 bits of the product
+ assembly {
+ let mm := mulmod(a, b, not(0))
+ prod0 := mul(a, b)
+ prod1 := sub(sub(mm, prod0), lt(mm, prod0))
+ }
- // Handle non-overflow cases, 256 by 256 division
- if (prod1 == 0) {
- require(denominator > 0);
- assembly {
- result := div(prod0, denominator)
- }
- return result;
- }
+ // Handle non-overflow cases, 256 by 256 division
+ if (prod1 == 0) {
+ require(denominator > 0);
+ assembly {
+ result := div(prod0, denominator)
+ }
+ return result;
+ }
- // Make sure the result is less than 2**256.
- // Also prevents denominator == 0
- require(denominator > prod1);
+ // Make sure the result is less than 2**256.
+ // Also prevents denominator == 0
+ require(denominator > prod1);
- ///////////////////////////////////////////////
- // 512 by 256 division.
- ///////////////////////////////////////////////
+ ///////////////////////////////////////////////
+ // 512 by 256 division.
+ ///////////////////////////////////////////////
- // Make division exact by subtracting the remainder from [prod1 prod0]
- // Compute remainder using mulmod
- uint256 remainder;
- assembly {
- remainder := mulmod(a, b, denominator)
- }
- // Subtract 256 bit number from 512 bit number
- assembly {
- prod1 := sub(prod1, gt(remainder, prod0))
- prod0 := sub(prod0, remainder)
- }
+ // Make division exact by subtracting the remainder from [prod1 prod0]
+ // Compute remainder using mulmod
+ uint256 remainder;
+ assembly {
+ remainder := mulmod(a, b, denominator)
+ }
+ // Subtract 256 bit number from 512 bit number
+ assembly {
+ prod1 := sub(prod1, gt(remainder, prod0))
+ prod0 := sub(prod0, remainder)
+ }
- // Factor powers of two out of denominator
- // Compute largest power of two divisor of denominator.
- // Always >= 1.
- uint256 twos = denominator & (~denominator + 1);
- // Divide denominator by power of two
- assembly {
- denominator := div(denominator, twos)
- }
+ // Factor powers of two out of denominator
+ // Compute largest power of two divisor of denominator.
+ // Always >= 1.
+ uint256 twos = denominator & (~denominator + 1);
+ // Divide denominator by power of two
+ assembly {
+ denominator := div(denominator, twos)
+ }
- // Divide [prod1 prod0] by the factors of two
- assembly {
- prod0 := div(prod0, twos)
- }
- // Shift in bits from prod1 into prod0. For this we need
- // to flip `twos` such that it is 2**256 / twos.
- // If twos is zero, then it becomes one
- assembly {
- twos := add(div(sub(0, twos), twos), 1)
- }
- prod0 |= prod1 * twos;
+ // Divide [prod1 prod0] by the factors of two
+ assembly {
+ prod0 := div(prod0, twos)
+ }
+ // Shift in bits from prod1 into prod0. For this we need
+ // to flip `twos` such that it is 2**256 / twos.
+ // If twos is zero, then it becomes one
+ assembly {
+ twos := add(div(sub(0, twos), twos), 1)
+ }
+ prod0 |= prod1 * twos;
- // Invert denominator mod 2**256
- // Now that denominator is an odd number, it has an inverse
- // modulo 2**256 such that denominator * inv = 1 mod 2**256.
- // Compute the inverse by starting with a seed that is correct
- // correct for four bits. That is, denominator * inv = 1 mod 2**4
- uint256 inv = (3 * denominator) ^ 2;
- // Now use Newton-Raphson iteration to improve the precision.
- // Thanks to Hensel's lifting lemma, this also works in modular
- // arithmetic, doubling the correct bits in each step.
- inv *= 2 - denominator * inv; // inverse mod 2**8
- inv *= 2 - denominator * inv; // inverse mod 2**16
- inv *= 2 - denominator * inv; // inverse mod 2**32
- inv *= 2 - denominator * inv; // inverse mod 2**64
- inv *= 2 - denominator * inv; // inverse mod 2**128
- inv *= 2 - denominator * inv; // inverse mod 2**256
+ // Invert denominator mod 2**256
+ // Now that denominator is an odd number, it has an inverse
+ // modulo 2**256 such that denominator * inv = 1 mod 2**256.
+ // Compute the inverse by starting with a seed that is correct
+ // correct for four bits. That is, denominator * inv = 1 mod 2**4
+ uint256 inv = (3 * denominator) ^ 2;
+ // Now use Newton-Raphson iteration to improve the precision.
+ // Thanks to Hensel's lifting lemma, this also works in modular
+ // arithmetic, doubling the correct bits in each step.
+ inv *= 2 - denominator * inv; // inverse mod 2**8
+ inv *= 2 - denominator * inv; // inverse mod 2**16
+ inv *= 2 - denominator * inv; // inverse mod 2**32
+ inv *= 2 - denominator * inv; // inverse mod 2**64
+ inv *= 2 - denominator * inv; // inverse mod 2**128
+ inv *= 2 - denominator * inv; // inverse mod 2**256
- // Because the division is now exact we can divide by multiplying
- // with the modular inverse of denominator. This will give us the
- // correct result modulo 2**256. Since the precoditions guarantee
- // that the outcome is less than 2**256, this is the final result.
- // We don't need to compute the high bits of the result and prod1
- // is no longer required.
- result = prod0 * inv;
- return result;
- }
+ // Because the division is now exact we can divide by multiplying
+ // with the modular inverse of denominator. This will give us the
+ // correct result modulo 2**256. Since the precoditions guarantee
+ // that the outcome is less than 2**256, this is the final result.
+ // We don't need to compute the high bits of the result and prod1
+ // is no longer required.
+ result = prod0 * inv;
+ return result;
+ }
}
diff --git a/contracts/external/SmartWalletChecker.sol b/contracts/external/SmartWalletChecker.sol
index 5ad1c41..4bead64 100644
--- a/contracts/external/SmartWalletChecker.sol
+++ b/contracts/external/SmartWalletChecker.sol
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
-pragma solidity 0.8.7;
+pragma solidity ^0.8.7;
/// @notice Interface of the `SmartWalletChecker` contracts of the protocol
interface SmartWalletChecker {
diff --git a/contracts/external/TransparentUpgradeableProxy.sol b/contracts/external/TransparentUpgradeableProxy.sol
index 2bb6caa..36474ca 100644
--- a/contracts/external/TransparentUpgradeableProxy.sol
+++ b/contracts/external/TransparentUpgradeableProxy.sol
@@ -31,11 +31,7 @@ contract TransparentUpgradeableProxy is ERC1967Proxy {
* @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and
* optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.
*/
- constructor(
- address _logic,
- address admin_,
- bytes memory _data
- ) payable ERC1967Proxy(_logic, _data) {
+ constructor(address _logic, address admin_, bytes memory _data) payable ERC1967Proxy(_logic, _data) {
assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1));
_changeAdmin(admin_);
}
diff --git a/contracts/interfaces/IAgToken.sol b/contracts/interfaces/IAgToken.sol
index f0d3a18..6409639 100644
--- a/contracts/interfaces/IAgToken.sol
+++ b/contracts/interfaces/IAgToken.sol
@@ -13,11 +13,7 @@ interface IAgToken is IERC20Upgradeable {
// ======================= `StableMaster` functions ============================
function mint(address account, uint256 amount) external;
- function burnFrom(
- uint256 amount,
- address burner,
- address sender
- ) external;
+ function burnFrom(uint256 amount, address burner, address sender) external;
function burnSelf(uint256 amount, address burner) external;
diff --git a/contracts/interfaces/IBondingCurve.sol b/contracts/interfaces/IBondingCurve.sol
deleted file mode 100644
index 2662d2f..0000000
--- a/contracts/interfaces/IBondingCurve.sol
+++ /dev/null
@@ -1,23 +0,0 @@
-// SPDX-License-Identifier: GPL-3.0
-
-pragma solidity ^0.8.7;
-
-import "./IAgToken.sol";
-import "./IOracle.sol";
-
-/// @title IBondingCurve
-/// @author Angle Core Team
-/// @notice Interface for the `BondingCurve` contract
-interface IBondingCurve {
- // ============================ User Functions =================================
-
- function buySoldToken(
- IAgToken _agToken,
- uint256 targetSoldTokenQuantity,
- uint256 maxAmountToPayInAgToken
- ) external;
-
- // ========================== Governance Functions =============================
-
- function changeOracle(IAgToken _agToken, IOracle _oracle) external;
-}
diff --git a/contracts/interfaces/ICollateralSettler.sol b/contracts/interfaces/ICollateralSettler.sol
deleted file mode 100644
index 3293462..0000000
--- a/contracts/interfaces/ICollateralSettler.sol
+++ /dev/null
@@ -1,14 +0,0 @@
-// SPDX-License-Identifier: GPL-3.0
-
-pragma solidity ^0.8.7;
-
-/// @title ICollateralSettler
-/// @author Angle Core Team
-/// @notice Interface for the collateral settlement contracts
-interface ICollateralSettler {
- function triggerSettlement(
- uint256 _oracleValue,
- uint256 _sanRate,
- uint256 _stocksUsers
- ) external;
-}
diff --git a/contracts/interfaces/IERC721.sol b/contracts/interfaces/IERC721.sol
deleted file mode 100644
index 53d07cf..0000000
--- a/contracts/interfaces/IERC721.sol
+++ /dev/null
@@ -1,46 +0,0 @@
-// SPDX-License-Identifier: GPL-3.0
-
-pragma solidity ^0.8.7;
-
-import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
-
-interface IERC721 is IERC165 {
- function balanceOf(address owner) external view returns (uint256 balance);
-
- function ownerOf(uint256 tokenId) external view returns (address owner);
-
- function safeTransferFrom(
- address from,
- address to,
- uint256 tokenId
- ) external;
-
- function transferFrom(
- address from,
- address to,
- uint256 tokenId
- ) external;
-
- function approve(address to, uint256 tokenId) external;
-
- function getApproved(uint256 tokenId) external view returns (address operator);
-
- function setApprovalForAll(address operator, bool _approved) external;
-
- function isApprovedForAll(address owner, address operator) external view returns (bool);
-
- function safeTransferFrom(
- address from,
- address to,
- uint256 tokenId,
- bytes calldata data
- ) external;
-}
-
-interface IERC721Metadata is IERC721 {
- function name() external view returns (string memory);
-
- function symbol() external view returns (string memory);
-
- function tokenURI(uint256 tokenId) external view returns (string memory);
-}
diff --git a/contracts/interfaces/IFeeDistributor.sol b/contracts/interfaces/IFeeDistributor.sol
deleted file mode 100644
index 8d89070..0000000
--- a/contracts/interfaces/IFeeDistributor.sol
+++ /dev/null
@@ -1,21 +0,0 @@
-// SPDX-License-Identifier: GPL-3.0
-
-pragma solidity ^0.8.7;
-
-/// @title IFeeDistributor
-/// @author Interface of the `FeeDistributor` contract
-/// @dev This interface is used by the `SurplusConverter` contract to send funds to the `FeeDistributor`
-interface IFeeDistributor {
- function burn(address token) external;
-}
-
-/// @title IFeeDistributorFront
-/// @author Interface for public use of the `FeeDistributor` contract
-/// @dev This interface is used for user related function
-interface IFeeDistributorFront {
- function token() external returns (address);
-
- function claim(address _addr) external returns (uint256);
-
- function claim(address[20] memory _addr) external returns (bool);
-}
\ No newline at end of file
diff --git a/contracts/interfaces/IFeeManager.sol b/contracts/interfaces/IFeeManager.sol
index afe30cc..adca175 100644
--- a/contracts/interfaces/IFeeManager.sol
+++ b/contracts/interfaces/IFeeManager.sol
@@ -16,17 +16,9 @@ interface IFeeManagerFunctions is IAccessControl {
// ================================= Governance ================================
- function deployCollateral(
- address[] memory governorList,
- address guardian,
- address _perpetualManager
- ) external;
-
- function setFees(
- uint256[] memory xArray,
- uint64[] memory yArray,
- uint8 typeChange
- ) external;
+ function deployCollateral(address[] memory governorList, address guardian, address _perpetualManager) external;
+
+ function setFees(uint256[] memory xArray, uint64[] memory yArray, uint8 typeChange) external;
function setHAFees(uint64 _haFeeDeposit, uint64 _haFeeWithdraw) external;
}
diff --git a/contracts/interfaces/IPerpetualManager.sol b/contracts/interfaces/IPerpetualManager.sol
index 6f3f493..3b3e55e 100644
--- a/contracts/interfaces/IPerpetualManager.sol
+++ b/contracts/interfaces/IPerpetualManager.sol
@@ -2,7 +2,7 @@
pragma solidity ^0.8.7;
-import "./IERC721.sol";
+import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";
import "./IFeeManager.sol";
import "./IOracle.sol";
import "./IAccessControl.sol";
@@ -19,19 +19,11 @@ interface IPerpetualManagerFront is IERC721Metadata {
uint256 minNetMargin
) external returns (uint256 perpetualID);
- function closePerpetual(
- uint256 perpetualID,
- address to,
- uint256 minCashOutAmount
- ) external;
+ function closePerpetual(uint256 perpetualID, address to, uint256 minCashOutAmount) external;
function addToPerpetual(uint256 perpetualID, uint256 amount) external;
- function removeFromPerpetual(
- uint256 perpetualID,
- uint256 amount,
- address to
- ) external;
+ function removeFromPerpetual(uint256 perpetualID, uint256 amount, address to) external;
function liquidatePerpetuals(uint256[] memory perpetualIDs) external;
@@ -60,11 +52,7 @@ interface IPerpetualManagerFunctions is IAccessControl {
function setFeeManager(IFeeManager feeManager_) external;
- function setHAFees(
- uint64[] memory _xHAFees,
- uint64[] memory _yHAFees,
- uint8 deposit
- ) external;
+ function setHAFees(uint64[] memory _xHAFees, uint64[] memory _yHAFees, uint8 deposit) external;
function setTargetAndLimitHAHedge(uint64 _targetHAHedge, uint64 _limitHAHedge) external;
diff --git a/contracts/interfaces/IPoolManager.sol b/contracts/interfaces/IPoolManager.sol
index 2d7757e..8e40854 100644
--- a/contracts/interfaces/IPoolManager.sol
+++ b/contracts/interfaces/IPoolManager.sol
@@ -40,11 +40,7 @@ interface IPoolManagerFunctions {
function debtOutstanding() external view returns (uint256);
- function report(
- uint256 _gain,
- uint256 _loss,
- uint256 _debtPayment
- ) external;
+ function report(uint256 _gain, uint256 _loss, uint256 _debtPayment) external;
// ============================ Governance =====================================
diff --git a/contracts/interfaces/ISanToken.sol b/contracts/interfaces/ISanToken.sol
index 2b85817..613347f 100644
--- a/contracts/interfaces/ISanToken.sol
+++ b/contracts/interfaces/ISanToken.sol
@@ -13,11 +13,7 @@ interface ISanToken is IERC20Upgradeable {
function mint(address account, uint256 amount) external;
- function burnFrom(
- uint256 amount,
- address burner,
- address sender
- ) external;
+ function burnFrom(uint256 amount, address burner, address sender) external;
function burnSelf(uint256 amount, address burner) external;
diff --git a/contracts/interfaces/IStableMaster.sol b/contracts/interfaces/IStableMaster.sol
index 10616dc..43b6e26 100644
--- a/contracts/interfaces/IStableMaster.sol
+++ b/contracts/interfaces/IStableMaster.sol
@@ -74,11 +74,7 @@ struct SLPData {
/// @author Angle Core Team
/// @notice Interface for the `StableMaster` contract
interface IStableMasterFunctions {
- function deploy(
- address[] memory _governorList,
- address _guardian,
- address _agToken
- ) external;
+ function deploy(address[] memory _governorList, address _guardian, address _agToken) external;
// ============================== Lending ======================================
@@ -96,12 +92,7 @@ interface IStableMasterFunctions {
function getCollateralRatio() external returns (uint256);
- function setFeeKeeper(
- uint64 feeMint,
- uint64 feeBurn,
- uint64 _slippage,
- uint64 _slippageFee
- ) external;
+ function setFeeKeeper(uint64 feeMint, uint64 feeBurn, uint64 _slippage, uint64 _slippageFee) external;
// ============================== AgToken ======================================
@@ -125,18 +116,9 @@ interface IStableMasterFunctions {
IPoolManager poolManager
) external;
- function setIncentivesForSLPs(
- uint64 _feesForSLPs,
- uint64 _interestsForSLPs,
- IPoolManager poolManager
- ) external;
+ function setIncentivesForSLPs(uint64 _feesForSLPs, uint64 _interestsForSLPs, IPoolManager poolManager) external;
- function setUserFees(
- IPoolManager poolManager,
- uint64[] memory _xFee,
- uint64[] memory _yFee,
- uint8 _mint
- ) external;
+ function setUserFees(IPoolManager poolManager, uint64[] memory _xFee, uint64[] memory _yFee, uint8 _mint) external;
function setTargetHAHedge(uint64 _targetHAHedge) external;
@@ -151,7 +133,9 @@ interface IStableMasterFunctions {
interface IStableMaster is IStableMasterFunctions {
function agToken() external view returns (address);
- function collateralMap(IPoolManager poolManager)
+ function collateralMap(
+ IPoolManager poolManager
+ )
external
view
returns (
diff --git a/contracts/interfaces/IStableMasterFront.sol b/contracts/interfaces/IStableMasterFront.sol
deleted file mode 100644
index 2728f06..0000000
--- a/contracts/interfaces/IStableMasterFront.sol
+++ /dev/null
@@ -1,40 +0,0 @@
-// SPDX-License-Identifier: GPL-3.0
-
-pragma solidity ^0.8.7;
-
-import "../interfaces/IPoolManager.sol";
-
-/// @title IStableMasterFront
-/// @author Angle Core Team
-/// @dev Front interface, meaning only user-facing functions
-interface IStableMasterFront {
- function mint(
- uint256 amount,
- address user,
- IPoolManager poolManager,
- uint256 minStableAmount
- ) external;
-
- function burn(
- uint256 amount,
- address burner,
- address dest,
- IPoolManager poolManager,
- uint256 minCollatAmount
- ) external;
-
- function deposit(
- uint256 amount,
- address user,
- IPoolManager poolManager
- ) external;
-
- function withdraw(
- uint256 amount,
- address burner,
- address dest,
- IPoolManager poolManager
- ) external;
-
- function agToken() external view returns (address);
-}
diff --git a/contracts/interfaces/IStakingRewards.sol b/contracts/interfaces/IStakingRewards.sol
index 135097f..560f434 100644
--- a/contracts/interfaces/IStakingRewards.sol
+++ b/contracts/interfaces/IStakingRewards.sol
@@ -10,11 +10,7 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IStakingRewardsFunctions {
function notifyRewardAmount(uint256 reward) external;
- function recoverERC20(
- address tokenAddress,
- address to,
- uint256 tokenAmount
- ) external;
+ function recoverERC20(address tokenAddress, address to, uint256 tokenAmount) external;
function setNewRewardsDistribution(address newRewardsDistribution) external;
}
diff --git a/contracts/interfaces/IVaultManager.sol b/contracts/interfaces/IVaultManager.sol
index d16dd77..29ee8dc 100644
--- a/contracts/interfaces/IVaultManager.sol
+++ b/contracts/interfaces/IVaultManager.sol
@@ -52,8 +52,8 @@ interface IVaultManagerFunctions {
/// this function can perform any of the allowed actions in the order of their choice
/// @param actions Set of actions to perform
/// @param datas Data to be decoded for each action: it can include like the `vaultID` or the
- /// @param from Address from which stablecoins will be taken if one action includes burning stablecoins. This address
- /// should either be the `msg.sender` or be approved by the latter
+ /// @param from Address from which stablecoins will be taken if one action includes burning stablecoins.
+ /// This address should either be the `msg.sender` or be approved by the latter
/// @param to Address to which stablecoins and/or collateral will be sent in case of
/// @return paymentData Struct containing the final transfers executed
/// @dev This function is optimized to reduce gas cost due to payment from or to the user and that expensive calls
@@ -69,8 +69,8 @@ interface IVaultManagerFunctions {
/// this function can perform any of the allowed actions in the order of their choice
/// @param actions Set of actions to perform
/// @param datas Data to be decoded for each action: it can include like the `vaultID` or the
- /// @param from Address from which stablecoins will be taken if one action includes burning stablecoins. This address
- /// should either be the `msg.sender` or be approved by the latter
+ /// @param from Address from which stablecoins will be taken if one action includes burning stablecoins.
+ /// This address should either be the `msg.sender` or be approved by the latter
/// @param to Address to which stablecoins and/or collateral will be sent in case of
/// @param who Address of the contract to handle in case of repayment of stablecoins from received collateral
/// @param repayData Data to pass to the repayment contract in case of
diff --git a/contracts/interfaces/IVeANGLE.sol b/contracts/interfaces/IVeANGLE.sol
index 53e254f..edda05a 100644
--- a/contracts/interfaces/IVeANGLE.sol
+++ b/contracts/interfaces/IVeANGLE.sol
@@ -1,13 +1,65 @@
// SPDX-License-Identifier: GPL-3.0
+// solhint-disable
pragma solidity ^0.8.7;
-import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
+import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
-/// @title IVeANGLE
+/// @title IveANGLE
/// @author Angle Core Team
/// @notice Interface for the `VeANGLE` contract
-interface IVeANGLE {
- // solhint-disable-next-line func-name-mixedcase
- function deposit_for(address addr, uint256 amount) external;
+interface IveANGLE is IERC20MetadataUpgradeable {
+ struct Point {
+ int128 bias;
+ int128 slope;
+ uint256 ts;
+ uint256 blk;
+ }
+
+ struct LockedBalance {
+ uint128 amount;
+ uint256 end;
+ }
+
+ function locked(address addr) external view returns (LockedBalance memory);
+
+ function set_emergency_withdrawal() external;
+
+ function emergency_withdrawal() external view returns (bool);
+
+ function withdraw_fast() external;
+
+ function initialize(
+ address admin,
+ address token_addr,
+ address smart_wallet_checker,
+ string memory name,
+ string memory symbol
+ ) external;
+
+ function checkpoint() external;
+
+ function withdraw() external;
+
+ function deposit_for(address addr, uint256 value) external;
+
+ function admin() external view returns (address);
+
+ function smart_wallet_checker() external view returns (address);
+
+ function create_lock(uint256 value, uint256 unlock_time) external;
+
+ function increase_amount(uint256 value) external;
+
+ function increase_unlock_time(uint256 unlock_time) external;
+
+ function initialized() external view returns (bool);
+
+ function balanceOf(address addr, uint256 ts) external view returns (uint256);
+
+ function find_user_timestamp_epoch(address addr, uint256 ts) external view returns (uint256);
+
+ function locked__end(address addr) external view returns (uint256);
+
+ function user_point_history(address addr, uint256 idx) external view returns (Point memory);
}
diff --git a/contracts/interfaces/IWETH.sol b/contracts/interfaces/IWETH.sol
index 1ca3256..bab53bb 100644
--- a/contracts/interfaces/IWETH.sol
+++ b/contracts/interfaces/IWETH.sol
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;
+
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IWETH is IERC20 {
diff --git a/contracts/interfaces/external/aave/IAave.sol b/contracts/interfaces/external/aave/IAave.sol
index 3476753..98ea17a 100644
--- a/contracts/interfaces/external/aave/IAave.sol
+++ b/contracts/interfaces/external/aave/IAave.sol
@@ -8,22 +8,11 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IAaveIncentivesController {
function getRewardsBalance(address[] calldata assets, address user) external view returns (uint256);
- function claimRewards(
- address[] calldata assets,
- uint256 amount,
- address to
- ) external returns (uint256);
+ function claimRewards(address[] calldata assets, uint256 amount, address to) external returns (uint256);
function getDistributionEnd() external view returns (uint256);
- function getAssetData(address asset)
- external
- view
- returns (
- uint256,
- uint256,
- uint256
- );
+ function getAssetData(address asset) external view returns (uint256, uint256, uint256);
}
interface IAToken is IERC20 {
@@ -31,18 +20,9 @@ interface IAToken is IERC20 {
}
interface ILendingPool {
- function deposit(
- address asset,
- uint256 amount,
- address onBehalfOf,
- uint16 referralCode
- ) external;
-
- function withdraw(
- address asset,
- uint256 amount,
- address to
- ) external returns (uint256);
+ function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external;
+
+ function withdraw(address asset, uint256 amount, address to) external returns (uint256);
function getReserveData(address asset) external view returns (DataTypes.ReserveData memory);
}
@@ -54,7 +34,9 @@ interface ILendingPoolAddressesProvider {
interface IProtocolDataProvider {
function ADDRESSES_PROVIDER() external view returns (ILendingPoolAddressesProvider);
- function getReserveConfigurationData(address asset)
+ function getReserveConfigurationData(
+ address asset
+ )
external
view
returns (
@@ -70,7 +52,9 @@ interface IProtocolDataProvider {
bool isFrozen
);
- function getReserveData(address asset)
+ function getReserveData(
+ address asset
+ )
external
view
returns (
@@ -95,14 +79,7 @@ interface IReserveInterestRateStrategy {
uint256 totalVariableDebt,
uint256 averageStableBorrowRate,
uint256 reserveFactor
- )
- external
- view
- returns (
- uint256 liquidityRate,
- uint256 stableBorrowRate,
- uint256 variableBorrowRate
- );
+ ) external view returns (uint256 liquidityRate, uint256 stableBorrowRate, uint256 variableBorrowRate);
}
interface IStakedAave {
diff --git a/contracts/interfaces/external/compound/CTokenI.sol b/contracts/interfaces/external/compound/CTokenI.sol
index 54d1941..bc4010d 100644
--- a/contracts/interfaces/external/compound/CTokenI.sol
+++ b/contracts/interfaces/external/compound/CTokenI.sol
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.7;
+
import "./InterestRateModel.sol";
interface CTokenI {
diff --git a/contracts/interfaces/external/compound/IComptroller.sol b/contracts/interfaces/external/compound/IComptroller.sol
index 1a7e2bb..1f6013a 100644
--- a/contracts/interfaces/external/compound/IComptroller.sol
+++ b/contracts/interfaces/external/compound/IComptroller.sol
@@ -7,10 +7,5 @@ import "./CTokenI.sol";
interface IComptroller {
function compSupplySpeeds(address cToken) external view returns (uint256);
- function claimComp(
- address[] memory holders,
- CTokenI[] memory cTokens,
- bool borrowers,
- bool suppliers
- ) external;
+ function claimComp(address[] memory holders, CTokenI[] memory cTokens, bool borrowers, bool suppliers) external;
}
diff --git a/contracts/interfaces/external/compound/InterestRateModel.sol b/contracts/interfaces/external/compound/InterestRateModel.sol
index 42acca1..b14446e 100755
--- a/contracts/interfaces/external/compound/InterestRateModel.sol
+++ b/contracts/interfaces/external/compound/InterestRateModel.sol
@@ -19,9 +19,5 @@ interface InterestRateModel {
) external view returns (uint256);
// Rinkeby function
- function getBorrowRate(
- uint256 cash,
- uint256 borrows,
- uint256 _reserves
- ) external view returns (uint256, uint256);
+ function getBorrowRate(uint256 cash, uint256 borrows, uint256 _reserves) external view returns (uint256, uint256);
}
diff --git a/contracts/interfaces/external/curve/Curve.sol b/contracts/interfaces/external/curve/Curve.sol
index 3b267d5..dac6c4c 100644
--- a/contracts/interfaces/external/curve/Curve.sol
+++ b/contracts/interfaces/external/curve/Curve.sol
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
-pragma solidity 0.8.7;
+pragma solidity ^0.8.7;
interface ICurveFi {
function get_virtual_price() external view returns (uint256);
@@ -27,34 +27,17 @@ interface ICurveFi {
function remove_liquidity(uint256 _amount, uint256[4] calldata amounts) external;
- function remove_liquidity_one_coin(
- uint256 _token_amount,
- int128 i,
- uint256 min_amount
- ) external;
+ function remove_liquidity_one_coin(uint256 _token_amount, int128 i, uint256 min_amount) external;
- function exchange(
- int128 from,
- int128 to,
- uint256 _from_amount,
- uint256 _min_to_amount
- ) external payable;
+ function exchange(int128 from, int128 to, uint256 _from_amount, uint256 _min_to_amount) external payable;
function balances(int128) external view returns (uint256);
- function get_dy(
- int128 from,
- int128 to,
- uint256 _from_amount
- ) external view returns (uint256);
+ function get_dy(int128 from, int128 to, uint256 _from_amount) external view returns (uint256);
function calc_token_amount(uint256[2] calldata amounts, bool is_deposit) external view returns (uint256);
}
interface Zap {
- function remove_liquidity_one_coin(
- uint256,
- int128,
- uint256
- ) external;
+ function remove_liquidity_one_coin(uint256, int128, uint256) external;
}
diff --git a/contracts/interfaces/external/lido/ISteth.sol b/contracts/interfaces/external/lido/ISteth.sol
index c5e9bde..83d3dc4 100644
--- a/contracts/interfaces/external/lido/ISteth.sol
+++ b/contracts/interfaces/external/lido/ISteth.sol
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
-pragma solidity 0.8.7;
+pragma solidity ^0.8.7;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
diff --git a/contracts/interfaces/external/lido/IWStETH.sol b/contracts/interfaces/external/lido/IWStETH.sol
index b6f4500..b1171c3 100644
--- a/contracts/interfaces/external/lido/IWStETH.sol
+++ b/contracts/interfaces/external/lido/IWStETH.sol
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0
-pragma solidity 0.8.7;
+pragma solidity ^0.8.7;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
diff --git a/contracts/staking/AngleDistributor.sol b/contracts/staking/AngleDistributor.sol
index 597befc..ffab92e 100644
--- a/contracts/staking/AngleDistributor.sol
+++ b/contracts/staking/AngleDistributor.sol
@@ -27,7 +27,7 @@ contract AngleDistributor is AngleDistributorEvents, ReentrancyGuardUpgradeable,
uint256 public constant RATE_REDUCTION_COEFFICIENT = 1007827884862117171; // 1.5 ^ (1/52) * 10**18
/// @notice Base used for computation
- uint256 public constant BASE = 10**18;
+ uint256 public constant BASE = 10 ** 18;
/// @notice Maps the address of a gauge to the last time this gauge received rewards
mapping(address => uint256) public lastTimeGaugePaid;
@@ -123,8 +123,8 @@ contract AngleDistributor is AngleDistributorEvents, ReentrancyGuardUpgradeable,
/// @dev The reason for having an internal function is that it's called by the `distributeReward` and the
/// `distributeRewardToMultipleGauges`
/// @dev Although they would need to be performed all the time this function is called, this function does not
- /// contain checks on whether distribution is on, and on whether rate should be reduced. These are done in each external
- /// function calling this function for gas efficiency
+ /// contain checks on whether distribution is on, and on whether rate should be reduced. These are done in
+ /// each external function calling this function for gas efficiency
function _distributeReward(address gaugeAddr) internal returns (uint256 weeksElapsed, uint256 rewardTally) {
// Checking if the gauge has been added or if it still possible to distribute rewards to this gauge
int128 gaugeType = IGaugeController(controller).gauge_types(gaugeAddr);
@@ -164,8 +164,8 @@ contract AngleDistributor is AngleDistributorEvents, ReentrancyGuardUpgradeable,
rewardTally += (weeklyRate * relWeightAtWeek * WEEK) / BASE;
// To get the rate of the week prior from the current rate we just have to multiply by the weekly division
- // factor
- // There may be some precisions error: inferred previous values of the rate may be different to what we would
+ // factor. There may be some
+ // precisions error: inferred previous values of the rate may be different to what we would
// have had if the rate had been computed correctly in these weeks: we expect from empirical observations
// this `weeklyRate` to be inferior to what the `rate` would have been
weeklyRate = (weeklyRate * RATE_REDUCTION_COEFFICIENT) / BASE;
@@ -290,11 +290,7 @@ contract AngleDistributor is AngleDistributorEvents, ReentrancyGuardUpgradeable,
/// @dev Added to support recovering LP Rewards and other mistaken tokens
/// from other systems to be distributed to holders
/// @dev This function could also be used to recover ANGLE tokens in case the rate got smaller
- function recoverERC20(
- address tokenAddress,
- address to,
- uint256 amount
- ) external onlyRole(GOVERNOR_ROLE) {
+ function recoverERC20(address tokenAddress, address to, uint256 amount) external onlyRole(GOVERNOR_ROLE) {
// If the token is the ANGLE token, we need to make sure that governance is not going to withdraw
// too many tokens and that it'll be able to sustain the weekly distribution forever
// This check assumes that `distributeReward` has been called for gauges and that there are no gauges
@@ -326,9 +322,10 @@ contract AngleDistributor is AngleDistributorEvents, ReentrancyGuardUpgradeable,
/// @param _delegateGauge Address of the new gauge delegate related to `gaugeAddr`
/// @param toggleInterface Whether we should toggle the fact that the `_delegateGauge` is built for automation or not
/// @dev This function can be used to remove delegating or introduce the pulling of rewards to a given address
- /// @dev If `gaugeAddr` is the zero address, this function updates the delegate gauge common to all gauges with type >= 2
- /// @dev The `toggleInterface` parameter has been added for convenience to save one transaction when adding a gauge delegate
- /// which supports the `notifyReward` interface
+ /// @dev If `gaugeAddr` is the zero address, this function updates the delegate gauge common to all gauges
+ /// with type >= 2
+ /// @dev The `toggleInterface` parameter has been added for convenience to save one transaction when adding
+ /// a gauge delegate which supports the `notifyReward` interface
function setDelegateGauge(
address gaugeAddr,
address _delegateGauge,
@@ -349,12 +346,12 @@ contract AngleDistributor is AngleDistributorEvents, ReentrancyGuardUpgradeable,
/// @notice Changes the ANGLE emission rate
/// @param _newRate New ANGLE emission rate
/// @dev It is important to be super wary when calling this function and to make sure that `distributeReward`
- /// has been called for all gauges in the past weeks. If not, gauges may get an incorrect distribution of ANGLE rewards
- /// for these past weeks based on the new rate and not on the old rate
- /// @dev Governance should thus make sure to call this function rarely and when it does to do it after the weekly `distributeReward`
- /// calls for all existing gauges
- /// @dev As this function assumes that `distributeReward` has been called during the week, it also assumes that the `startEpochSupply`
- /// parameter has been put up to date
+ /// has been called for all gauges in the past weeks. If not, gauges may get an incorrect distribution
+ /// of ANGLE rewards for these past weeks based on the new rate and not on the old rate
+ /// @dev Governance should thus make sure to call this function rarely and when it does to do it after the weekly
+ /// `distributeReward` calls for all existing gauges
+ /// @dev As this function assumes that `distributeReward` has been called during the week, it also assumes that
+ /// the `startEpochSupply` parameter has been put up to date
function setRate(uint256 _newRate) external onlyRole(GOVERNOR_ROLE) {
// Checking if the new rate is compatible with the amount of ANGLE tokens this contract has in balance
// This check assumes, like this function, that `distributeReward` has correctly been called before
@@ -371,13 +368,13 @@ contract AngleDistributor is AngleDistributorEvents, ReentrancyGuardUpgradeable,
/// @param gaugeAddr Gauge to toggle the status of
/// @dev It is impossible to kill a gauge in the `GaugeController` contract, for this reason killing of gauges
/// takes place in the `AngleDistributor` contract
- /// @dev This means that people could vote for a gauge in the gauge controller contract but that rewards are not going
- /// to be distributed to it in the end: people would need to remove their weights on the gauge killed to end the diminution
- /// in rewards
- /// @dev In the case of a gauge being killed, this function resets the timestamps at which this gauge has been approved and
- /// disapproves the gauge to spend the token
- /// @dev It should be cautiously called by governance as it could result in less ANGLE overall rewards than initially planned
- /// if people do not remove their voting weights to the killed gauge
+ /// @dev This means that people could vote for a gauge in the gauge controller contract but that rewards are
+ /// not going to be distributed to it in the end: people would need to remove their weights on the gauge killed
+ /// to end the diminution in rewards
+ /// @dev In the case of a gauge being killed, this function resets the timestamps at which this gauge has been
+ /// approved and disapproves the gauge to spend the token
+ /// @dev It should be cautiously called by governance as it could result in less ANGLE overall rewards than
+ /// initially planned if people do not remove their voting weights to the killed gauge
function toggleGauge(address gaugeAddr) external onlyRole(GOVERNOR_ROLE) {
bool gaugeKilledMem = killedGauges[gaugeAddr];
if (!gaugeKilledMem) {
diff --git a/contracts/staking/RewardsDistributor.sol b/contracts/staking/RewardsDistributor.sol
index df6b97d..e26a32a 100644
--- a/contracts/staking/RewardsDistributor.sol
+++ b/contracts/staking/RewardsDistributor.sol
@@ -56,11 +56,7 @@ contract RewardsDistributor is RewardsDistributorEvents, IRewardsDistributor, Ac
/// @param governorList List of the governor addresses of the protocol
/// @param guardian The guardian address, optional
/// @param rewardTokenAddress The ERC20 token to distribute
- constructor(
- address[] memory governorList,
- address guardian,
- address rewardTokenAddress
- ) {
+ constructor(address[] memory governorList, address guardian, address rewardTokenAddress) {
require(rewardTokenAddress != address(0) && guardian != address(0), "0");
require(governorList.length > 0, "47");
rewardToken = IERC20(rewardTokenAddress);
@@ -185,11 +181,12 @@ contract RewardsDistributor is RewardsDistributorEvents, IRewardsDistributor, Ac
/// @param _stakingContract Address of the staking contract
/// @param _duration Time frame during which tokens will be distributed
/// @param _incentiveAmount Incentive amount given to keepers calling the update function
- /// @param _updateFrequency Frequency when it is possible to call the update function and give tokens to the staking contract
+ /// @param _updateFrequency Frequency when it is possible to call the update function and give tokens to the
+ /// staking contract
/// @param _amountToDistribute Amount of gov tokens to give to the staking contract across all drips
/// @dev Called by governance to activate a contract
- /// @dev After setting a new staking contract, everything is as if the contract had already been set for `_updateFrequency`
- /// meaning that it is possible to `drip` the staking contract immediately after that
+ /// @dev After setting a new staking contract, everything is as if the contract had already been set for
+ /// `_updateFrequency` meaning that it is possible to `drip` the staking contract immediately after that
function setStakingContract(
address _stakingContract,
uint256 _duration,
@@ -222,11 +219,10 @@ contract RewardsDistributor is RewardsDistributorEvents, IRewardsDistributor, Ac
/// @notice Sets the update frequency
/// @param _updateFrequency New update frequency
/// @param stakingContract Reference to the staking contract
- function setUpdateFrequency(uint256 _updateFrequency, IStakingRewards stakingContract)
- external
- override
- onlyRole(GUARDIAN_ROLE)
- {
+ function setUpdateFrequency(
+ uint256 _updateFrequency,
+ IStakingRewards stakingContract
+ ) external override onlyRole(GUARDIAN_ROLE) {
StakingParameters storage stakingParams = stakingContractsMap[stakingContract];
require(stakingParams.duration > 0, "80");
require(stakingParams.duration >= _updateFrequency, "87");
@@ -237,11 +233,10 @@ contract RewardsDistributor is RewardsDistributorEvents, IRewardsDistributor, Ac
/// @notice Sets the incentive amount for calling drip
/// @param _incentiveAmount New incentive amount
/// @param stakingContract Reference to the staking contract
- function setIncentiveAmount(uint256 _incentiveAmount, IStakingRewards stakingContract)
- external
- override
- onlyRole(GUARDIAN_ROLE)
- {
+ function setIncentiveAmount(
+ uint256 _incentiveAmount,
+ IStakingRewards stakingContract
+ ) external override onlyRole(GUARDIAN_ROLE) {
StakingParameters storage stakingParams = stakingContractsMap[stakingContract];
require(stakingParams.duration > 0, "80");
stakingParams.incentiveAmount = _incentiveAmount;
@@ -251,11 +246,10 @@ contract RewardsDistributor is RewardsDistributorEvents, IRewardsDistributor, Ac
/// @notice Sets the new amount to distribute to a staking contract
/// @param _amountToDistribute New amount to distribute
/// @param stakingContract Reference to the staking contract
- function setAmountToDistribute(uint256 _amountToDistribute, IStakingRewards stakingContract)
- external
- override
- onlyRole(GUARDIAN_ROLE)
- {
+ function setAmountToDistribute(
+ uint256 _amountToDistribute,
+ IStakingRewards stakingContract
+ ) external override onlyRole(GUARDIAN_ROLE) {
StakingParameters storage stakingParams = stakingContractsMap[stakingContract];
require(stakingParams.duration > 0, "80");
require(stakingParams.distributedRewards < _amountToDistribute, "88");
diff --git a/contracts/staking/StakingRewards.sol b/contracts/staking/StakingRewards.sol
index ee14dee..6f15faa 100644
--- a/contracts/staking/StakingRewards.sol
+++ b/contracts/staking/StakingRewards.sol
@@ -71,12 +71,7 @@ contract StakingRewards is StakingRewardsEvents, IStakingRewards, ReentrancyGuar
/// @param _rewardToken ERC20 token given as reward
/// @param _stakingToken ERC20 token used for staking
/// @param _rewardsDuration Duration of the staking contract
- constructor(
- address _rewardsDistribution,
- address _rewardToken,
- address _stakingToken,
- uint256 _rewardsDuration
- ) {
+ constructor(address _rewardsDistribution, address _rewardToken, address _stakingToken, uint256 _rewardsDuration) {
require(_stakingToken != address(0) && _rewardToken != address(0) && _rewardsDistribution != address(0), "0");
// We are not checking the compatibility of the reward token between the distributor and this contract here
@@ -87,7 +82,7 @@ contract StakingRewards is StakingRewardsEvents, IStakingRewards, ReentrancyGuar
rewardsDuration = _rewardsDuration;
rewardsDistribution = _rewardsDistribution;
- stakingBase = 10**IERC20Metadata(_stakingToken).decimals();
+ stakingBase = 10 ** IERC20Metadata(_stakingToken).decimals();
}
// ============================ Modifiers ======================================
@@ -201,12 +196,10 @@ contract StakingRewards is StakingRewardsEvents, IStakingRewards, ReentrancyGuar
/// @notice Allows to stake on behalf of another address
/// @param amount Amount to stake
/// @param onBehalf Address to stake onBehalf of
- function stakeOnBehalf(uint256 amount, address onBehalf)
- external
- nonReentrant
- zeroCheck(onBehalf)
- updateReward(onBehalf)
- {
+ function stakeOnBehalf(
+ uint256 amount,
+ address onBehalf
+ ) external nonReentrant zeroCheck(onBehalf) updateReward(onBehalf) {
_stake(amount, onBehalf);
}
@@ -227,13 +220,9 @@ contract StakingRewards is StakingRewardsEvents, IStakingRewards, ReentrancyGuar
/// @notice Adds rewards to be distributed
/// @param reward Amount of reward tokens to distribute
/// @dev This reward will be distributed during `rewardsDuration` set previously
- function notifyRewardAmount(uint256 reward)
- external
- override
- onlyRewardsDistribution
- nonReentrant
- updateReward(address(0))
- {
+ function notifyRewardAmount(
+ uint256 reward
+ ) external override onlyRewardsDistribution nonReentrant updateReward(address(0)) {
if (block.timestamp >= periodFinish) {
// If no reward is currently being distributed, the new rate is just `reward / duration`
rewardRate = reward / rewardsDuration;
@@ -261,11 +250,7 @@ contract StakingRewards is StakingRewardsEvents, IStakingRewards, ReentrancyGuar
/// @param to Address to transfer to
/// @param amount Amount to transfer
/// @dev A use case would be to claim tokens if the staked tokens accumulate rewards
- function recoverERC20(
- address tokenAddress,
- address to,
- uint256 amount
- ) external override onlyRewardsDistribution {
+ function recoverERC20(address tokenAddress, address to, uint256 amount) external override onlyRewardsDistribution {
require(tokenAddress != address(stakingToken) && tokenAddress != address(rewardToken), "20");
IERC20(tokenAddress).safeTransfer(to, amount);
@@ -275,8 +260,8 @@ contract StakingRewards is StakingRewardsEvents, IStakingRewards, ReentrancyGuar
/// @notice Changes the rewards distributor associated to this contract
/// @param _rewardsDistribution Address of the new rewards distributor contract
/// @dev This function was also added by Angle Core Team
- /// @dev A compatibility check of the reward token is already performed in the current `RewardsDistributor` implementation
- /// which has right to call this function
+ /// @dev A compatibility check of the reward token is already performed in the current `RewardsDistributor`
+ /// implementation which has right to call this function
function setNewRewardsDistribution(address _rewardsDistribution) external override onlyRewardsDistribution {
rewardsDistribution = _rewardsDistribution;
emit RewardsDistributionUpdated(_rewardsDistribution);
diff --git a/contracts/utils/VyperDeployer.sol b/contracts/utils/VyperDeployer.sol
index 0650a23..2e72418 100644
--- a/contracts/utils/VyperDeployer.sol
+++ b/contracts/utils/VyperDeployer.sol
@@ -1,6 +1,9 @@
// SPDX-License-Identifier: UNLICENSED
+pragma solidity >=0.8.13;
-pragma solidity ^0.8.7;
+// solhint-disable
+
+//Taken from: https://github.com/0xKitsune/Foundry-Vyper
///@notice This cheat codes interface is named _CheatCodes so you can use the CheatCodes interface in other testing files without errors
interface _CheatCodes {
@@ -15,14 +18,14 @@ contract VyperDeployer {
///@notice Compiles a Vyper contract and returns the address that the contract was deployeod to
///@notice If deployment fails, an error will be thrown
- ///@param fileName - The file name of the Vyper contract. For example, the file name for "SimpleStore.vy" is "SimpleStore"
+ ///@param filepath - The file name of the Vyper contract. For example, the file name for "SimpleStore.vy" is "SimpleStore"
///@return deployedAddress - The address that the contract was deployed to
- function deployContract(string memory fileName) public returns (address) {
+ function deployContract(string memory filepath) public returns (address) {
///@notice create a list of strings with the commands necessary to compile Vyper contracts
string[] memory cmds = new string[](2);
cmds[0] = "vyper";
- cmds[1] = string.concat("vyper_contracts/", fileName, ".vy");
+ cmds[1] = filepath;
///@notice compile the Vyper contract and return the bytecode
bytes memory bytecode = cheatCodes.ffi(cmds);
@@ -48,7 +51,7 @@ contract VyperDeployer {
///@notice create a list of strings with the commands necessary to compile Vyper contracts
string[] memory cmds = new string[](2);
cmds[0] = "vyper";
- cmds[1] = string.concat("vyper_contracts/", fileName, ".vy");
+ cmds[1] = string.concat("test/external/", fileName, ".vy");
///@notice compile the Vyper contract and return the bytecode
bytes memory _bytecode = cheatCodes.ffi(cmds);
@@ -68,48 +71,4 @@ contract VyperDeployer {
///@notice return the address that the contract was deployed to
return deployedAddress;
}
-
- /// @dev Consider listening to the Blueprint if you haven't already
- /// @param fileName - The file name of the Blueprint Contract
- function deployBlueprint(string memory fileName) public returns (address) {
- ///@notice create a list of strings with the commands necessary to compile Vyper contracts
- string[] memory cmds = new string[](2);
- cmds[0] = "vyper";
- cmds[1] = string.concat("vyper_contracts/", fileName, ".vy");
-
- ///@notice compile the Vyper contract and return the bytecode
- bytes memory bytecode = cheatCodes.ffi(cmds);
-
- require(bytecode.length > 0, "Initcodes length must be greater than 0");
-
- /// @notice prepend needed items for Blueprint ERC
- /// See https://eips.ethereum.org/EIPS/eip-5202 for more details
- bytes memory eip_5202_bytecode = bytes.concat(
- hex"fe", // EIP_5202_EXECUTION_HALT_BYTE
- hex"71", // EIP_5202_BLUEPRINT_IDENTIFIER_BYTE
- hex"00", // EIP_5202_VERSION_BYTE
- bytecode
- );
-
- bytes2 len = bytes2(uint16(eip_5202_bytecode.length));
-
- /// @notice prepend the deploy preamble
- bytes memory deployBytecode = bytes.concat(
- hex"61", // DEPLOY_PREAMBLE_INITIAL_BYTE
- len, // DEPLOY_PREAMBLE_BYTE_LENGTH
- hex"3d81600a3d39f3", // DEPLOY_PREABLE_POST_LENGTH_BYTES
- eip_5202_bytecode
- );
-
- ///@notice check that the deployment was successful
- address deployedAddress;
- assembly {
- deployedAddress := create(0, add(deployBytecode, 0x20), mload(deployBytecode))
- }
-
- require(deployedAddress != address(0), "VyperDeployer could not deploy contract");
-
- ///@notice return the address that the contract was deployed to
- return deployedAddress;
- }
}
diff --git a/foundry.toml b/foundry.toml
index e314232..3db7807 100644
--- a/foundry.toml
+++ b/foundry.toml
@@ -6,19 +6,20 @@ libs = ["lib"]
script = "scripts"
cache_path = "cache"
gas_reports = ["*"]
-via_ir = true
sizes = true
optimizer = true
optimizer_runs = 1000
-solc_version = "0.8.7"
+solc_version = "0.8.22"
ffi = true
+via_ir = true
[fuzz]
runs = 10000
[invariant]
-runs = 1000
-depth = 30
+runs = 10
+depth = 100
+fail_on_revert = true
[rpc_endpoints]
arbitrum = "${ETH_NODE_URI_ARBITRUM}"
@@ -34,16 +35,7 @@ bsc = "${ETH_NODE_URI_BSC}"
base = "${ETH_NODE_URI_BASE}"
[etherscan]
-arbitrum = { key = "${ARBITRUM_ETHERSCAN_API_KEY}" }
-gnosis = { key = "${GNOSIS_ETHERSCAN_API_KEY}" , url = "https://api.gnosisscan.io/api"}
-mainnet = { key = "${MAINNET_ETHERSCAN_API_KEY}" }
-optimism = { key = "${OPTIMISM_ETHERSCAN_API_KEY}" }
-polygon = { key = "${POLYGON_ETHERSCAN_API_KEY}" }
-avalanche = { key = "${AVALANCHE_ETHERSCAN_API_KEY}" }
-celo = { key = "${CELO_ETHERSCAN_API_KEY}", url = "https://api.celoscan.io/api" }
-base = { key = "${BASE_ETHERSCAN_API_KEY}", url = "https://api.basescan.org/api" }
-polygonzkevm = { key = "${POLYGONZKEVM_ETHERSCAN_API_KEY}", url = "https://api-zkevm.polygonscan.com/api" }
-bsc = { key = "${BSC_ETHERSCAN_API_KEY}"}
+
[profile.dev]
optimizer = true
@@ -55,9 +47,9 @@ gas_reports = ["*"]
runs = 2000
[profile.dev.invariant]
-runs = 10
-depth = 1
-fail_on_revert = false
+runs = 100
+depth = 10
+fail_on_revert = true
[profile.ci]
src = "test"
@@ -70,4 +62,4 @@ runs = 100
[profile.ci.invariant]
runs = 10
depth = 30
-fail_on_revert = false
+fail_on_revert = true
diff --git a/lib/utils b/lib/utils
index 03a279e..41388c6 160000
--- a/lib/utils
+++ b/lib/utils
@@ -1 +1 @@
-Subproject commit 03a279efc8569b5b6f1a2925effeb5e966a02f03
+Subproject commit 41388c6ea9c45b05b92155356d6e700802fdb566
diff --git a/package.json b/package.json
index 4b559c4..8c81d99 100644
--- a/package.json
+++ b/package.json
@@ -13,7 +13,7 @@
"fork": "bash helpers/fork.sh",
"run": "docker run -it --rm -v $(pwd):/app -w /app ghcr.io/foundry-rs/foundry sh",
"script:fork": "source .env && forge script --skip test --fork-url fork --broadcast -vvvv",
- "test:unit": "forge test -vvv --gas-report --match-path \"test/unit/**/*.sol\"",
+ "test:unit": "forge test -vvvv --gas-report --match-path \"test/unit/**/*.sol\"",
"test:invariant": "forge test -vvv --gas-report --match-path \"test/invariant/**/*.sol\"",
"test:fuzz": "forge test -vvv --gas-report --match-path \"test/fuzz/**/*.sol\"",
"test": "FOUNDRY_PROFILE=dev forge test -vvv",
@@ -38,5 +38,7 @@
"solhint": "^3.5.1",
"solhint-plugin-prettier": "^0.0.5"
},
- "dependencies": {}
+ "dependencies": {
+ "@angleprotocol/sdk": "^0.38.0"
+ }
}
diff --git a/remappings.txt b/remappings.txt
index 20ce6b6..c9238f4 100644
--- a/remappings.txt
+++ b/remappings.txt
@@ -2,4 +2,5 @@ ds-test/=lib/forge-std/lib/ds-test/src/
forge-std/=lib/forge-std/src/
@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts
@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts
-utils/=lib/utils/
\ No newline at end of file
+utils/=lib/utils/
+contracts/=contracts/
\ No newline at end of file
diff --git a/scripts/BasicScript.s.sol b/scripts/BasicScript.s.sol
deleted file mode 100644
index 8c1e77d..0000000
--- a/scripts/BasicScript.s.sol
+++ /dev/null
@@ -1,20 +0,0 @@
-// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.7;
-
-import "forge-std/Script.sol";
-import { console } from "forge-std/console.sol";
-
-contract MyScript is Script {
- function test() external {
- vm.startBroadcast();
-
- address _sender = address(uint160(uint256(keccak256(abi.encodePacked("sender")))));
- address _receiver = address(uint160(uint256(keccak256(abi.encodePacked("receiver")))));
-
- // deal(address(token), _sender, 1 ether);
- // vm.prank(_sender);
- // token.transfer(_receiver, 1 ether);
-
- vm.stopBroadcast();
- }
-}
diff --git a/scripts/DeployVeAngle.s.sol b/scripts/DeployVeAngle.s.sol
new file mode 100644
index 0000000..0f5c436
--- /dev/null
+++ b/scripts/DeployVeAngle.s.sol
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.7;
+
+import "forge-std/Script.sol";
+import { console } from "forge-std/console.sol";
+import { VyperDeployer } from "contracts/utils/VyperDeployer.sol";
+import "./Utils.s.sol";
+
+contract DeployVeAngleScript is Script, Utils, VyperDeployer {
+ function run() external {
+ uint256 deployerPrivateKey = vm.deriveKey(vm.envString("MNEMONIC_MAINNET"), "m/44'/60'/0'/0/", 0);
+
+ address deployer = vm.addr(deployerPrivateKey);
+ console.log("Deployer address: ", deployer);
+
+ vm.startBroadcast(deployerPrivateKey);
+ address veANGLE = deployContract("contracts/dao/veANGLE.vy");
+ vm.stopBroadcast();
+ console.log("veANGLE deployed at: ", veANGLE);
+ }
+}
diff --git a/scripts/Simulate.s.sol b/scripts/Simulate.s.sol
deleted file mode 100644
index d922378..0000000
--- a/scripts/Simulate.s.sol
+++ /dev/null
@@ -1,22 +0,0 @@
-// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.7;
-
-import "forge-std/Script.sol";
-import { console } from "forge-std/console.sol";
-
-contract Simulate is Script {
- error WrongCall();
-
- function run() external {
- // TODO replace with your inputs
- address sender = address(0x0274a704a6D9129F90A62dDC6f6024b33EcDad36);
- address contractAddress = address(0x3Ef3D8bA38EBe18DB133cEc108f4D14CE00Dd9Ae);
- // remove the 0x
- bytes
- memory data = hex"71ee95c0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000274a704a6d9129f90a62ddc6f6024b33ecdad3600000000000000000000000000000000000000000000000000000000000000010000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f984000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000427abf85e5d121ac000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000811e1782af6373843046497b3be2c5b25f13037b02c218c5a1a5be24666434d169ca949b7c3d8c763a566075f024a19b4565aba390e00f197fff97adb2f9ef8b0eee43dfe473f564bbd71b106e37928d4f052afe2abf8a42e5f07aded57af2766943bc7bedecf531200d4ca454185d135e6933aa3cff5c53a55f45033135d3a01aae71a2ff3d1e34342bdb86d6348a9da5c8384085f743bb2451aa846b5f667690ccb7b7b1fe363d3e286addaaff93de4a258308fae35fb008580bc25873284f63b37592378acc9f27d211017550c57ae97d0e9cc944d3f90bf54147a69fedeed81940d2088ad7b84767ae8569a9202e23aa0f8204a30b365916d5cefb60c1dfe";
-
- vm.prank(sender);
- (bool success, ) = contractAddress.call(data);
- if (!success) revert WrongCall();
- }
-}
diff --git a/test/Fixture.t.sol b/test/Fixture.t.sol
new file mode 100644
index 0000000..6524e23
--- /dev/null
+++ b/test/Fixture.t.sol
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.7;
+
+import "forge-std/Test.sol";
+import { IveANGLE } from "contracts/interfaces/IVeANGLE.sol";
+import { VyperDeployer } from "contracts/utils/VyperDeployer.sol";
+import { ANGLE } from "contracts/dao/ANGLE.sol";
+import "utils/src/CommonUtils.sol";
+
+contract Fixture is Test, CommonUtils {
+ VyperDeployer public vyperDeployer;
+
+ IveANGLE public veANGLE;
+ address public admin;
+ ANGLE public Angle;
+ address public checker;
+
+ address public alice;
+ address public bob;
+
+ function setUp() public virtual {
+ uint256 CHAIN_SOURCE = CHAIN_ETHEREUM;
+
+ vyperDeployer = new VyperDeployer();
+ veANGLE = IveANGLE(vyperDeployer.deployContract("contracts/dao/veANGLE.vy"));
+
+ vm.createSelectFork("mainnet");
+ IveANGLE forkedveANGLE = IveANGLE(_chainToContract(CHAIN_SOURCE, ContractType.veANGLE));
+
+ admin = forkedveANGLE.admin();
+ string memory name = forkedveANGLE.name();
+ string memory symbol = forkedveANGLE.symbol();
+ checker = forkedveANGLE.smart_wallet_checker();
+ Angle = ANGLE(_chainToContract(CHAIN_SOURCE, ContractType.Angle));
+
+ veANGLE.initialize(admin, address(Angle), checker, name, symbol);
+
+ alice = makeAddr("alice");
+ bob = makeAddr("bob");
+ }
+}
diff --git a/test/fuzz/.gitkeep b/test/fuzz/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/test/fuzz/EmergencyWithdrawal.t.sol b/test/fuzz/EmergencyWithdrawal.t.sol
new file mode 100644
index 0000000..6080a9b
--- /dev/null
+++ b/test/fuzz/EmergencyWithdrawal.t.sol
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.7;
+
+import { Fixture, IveANGLE } from "../Fixture.t.sol";
+import { console } from "forge-std/console.sol";
+
+contract EmergencyWithdrawalFuzz is Fixture {
+ function test_emergencyWithdrawalFuzz_Normal(uint256[10] memory balances, uint256[10] memory durations) external {
+ address[] memory accounts = new address[](balances.length);
+ for (uint i = 0; i < accounts.length; i++) {
+ accounts[i] = address(uint160(uint256(keccak256(abi.encodePacked("account", i)))));
+ }
+ for (uint i = 0; i < accounts.length; i++) {
+ durations[i] = bound(durations[i], 1 weeks, 365 days * 4);
+ balances[i] = bound(balances[i], 1e18, 1e22);
+ deal(address(Angle), accounts[i], balances[i]);
+
+ vm.startPrank(accounts[i], accounts[i]);
+ Angle.approve(address(veANGLE), balances[i]);
+ veANGLE.create_lock(balances[i], block.timestamp + durations[i]);
+ vm.stopPrank();
+ }
+
+ assertEq(veANGLE.emergency_withdrawal(), false);
+
+ vm.prank(admin);
+ veANGLE.set_emergency_withdrawal();
+
+ assertEq(veANGLE.emergency_withdrawal(), true);
+
+ for (uint i = 0; i < accounts.length; i++) {
+ assertEq(Angle.balanceOf(accounts[i]), 0);
+
+ vm.prank(accounts[i]);
+ veANGLE.withdraw_fast();
+ assertEq(Angle.balanceOf(accounts[i]), balances[i]);
+
+ vm.prank(accounts[i]);
+ veANGLE.withdraw_fast();
+ assertEq(Angle.balanceOf(accounts[i]), balances[i]);
+ }
+ }
+
+ function test_emergencyWithdrawalFuzz_WithTimeWraps(
+ uint256[10] memory balances,
+ uint256[10] memory durations,
+ uint256[10] memory timeWraps
+ ) external {
+ address[] memory accounts = new address[](balances.length);
+ for (uint i = 0; i < accounts.length; i++) {
+ accounts[i] = address(uint160(uint256(keccak256(abi.encodePacked("account", i)))));
+ }
+
+ for (uint i = 0; i < accounts.length; i++) {
+ durations[i] = bound(durations[i], 1 weeks, 365 days * 4);
+ balances[i] = bound(balances[i], 1e18, 1e22);
+ deal(address(Angle), accounts[i], balances[i]);
+ vm.startPrank(accounts[i], accounts[i]);
+ Angle.approve(address(veANGLE), balances[i]);
+ veANGLE.create_lock(balances[i], block.timestamp + durations[i]);
+ vm.stopPrank();
+ }
+
+ assertEq(veANGLE.emergency_withdrawal(), false);
+
+ vm.prank(admin);
+ veANGLE.set_emergency_withdrawal();
+
+ assertEq(veANGLE.emergency_withdrawal(), true);
+
+ for (uint i = 0; i < accounts.length; i++) {
+ timeWraps[i] = bound(timeWraps[i], 0, 365 days * 4 + 1);
+ assertEq(Angle.balanceOf(accounts[i]), 0);
+
+ vm.warp(block.timestamp + timeWraps[i]);
+
+ vm.prank(accounts[i]);
+ veANGLE.withdraw_fast();
+ assertEq(Angle.balanceOf(accounts[i]), balances[i]);
+
+ vm.prank(accounts[i]);
+ veANGLE.withdraw_fast();
+ assertEq(Angle.balanceOf(accounts[i]), balances[i]);
+ }
+ }
+}
diff --git a/test/invariant/.gitkeep b/test/invariant/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/test/invariant/LocksInvariants.t.sol b/test/invariant/LocksInvariants.t.sol
new file mode 100644
index 0000000..24dd623
--- /dev/null
+++ b/test/invariant/LocksInvariants.t.sol
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: UNLICENSED
+
+pragma solidity ^0.8.7;
+
+import "../Fixture.t.sol";
+import { Locker } from "./actors/Locker.t.sol";
+import { Param } from "./actors/Param.t.sol";
+import { TimestampStore } from "./stores/TimestampStore.t.sol";
+import { LockStore, Lock } from "./stores/LockStore.t.sol";
+import { IERC20 } from "oz/token/ERC20/IERC20.sol";
+import "oz/utils/Strings.sol";
+
+//solhint-disable
+import { console } from "forge-std/console.sol";
+
+contract LocksInvariants is Fixture {
+ uint256 internal constant _NUM_LOCKERS = 10;
+ uint256 internal constant _NUM_PARAMS = 1;
+
+ Locker internal _lockerHandler;
+ Param internal _paramHandler;
+ TimestampStore internal _timestampStore;
+ LockStore internal _lockStore;
+
+ modifier useCurrentTimestampBlock() {
+ vm.warp(_timestampStore.currentTimestamp());
+ vm.roll(_timestampStore.currentBlockNumber());
+ _;
+ }
+
+ function concat(string memory a, string memory b) public pure returns (string memory) {
+ return string(abi.encodePacked(a, b));
+ }
+
+ function setUp() public virtual override {
+ super.setUp();
+ _timestampStore = new TimestampStore();
+ _lockStore = new LockStore();
+ _lockerHandler = new Locker(_NUM_LOCKERS, IERC20(address(Angle)), veANGLE, _timestampStore, _lockStore);
+ _paramHandler = new Param(_NUM_PARAMS, _timestampStore);
+
+ // Label newly created addresses
+ for (uint256 i; i < _NUM_LOCKERS; i++) {
+ vm.label(_lockerHandler.actors(i), concat("Locker ", Strings.toString(i)));
+ }
+ vm.label({ account: address(_timestampStore), newLabel: "TimestampStore" });
+ vm.label({ account: address(_paramHandler), newLabel: "Param" });
+ targetContract(address(_lockerHandler));
+ targetContract(address(_paramHandler));
+
+ {
+ bytes4[] memory selectors = new bytes4[](4);
+ selectors[0] = Locker.createLock.selector;
+ selectors[1] = Locker.withdraw.selector;
+ selectors[2] = Locker.extendLockTime.selector;
+ selectors[3] = Locker.extendLockAmount.selector;
+ targetSelector(FuzzSelector({ addr: address(_lockerHandler), selectors: selectors }));
+ }
+ {
+ bytes4[] memory selectors = new bytes4[](1);
+ selectors[0] = Param.wrap.selector;
+ targetSelector(FuzzSelector({ addr: address(_paramHandler), selectors: selectors }));
+ }
+ }
+
+ function invariant_RightBalanceAtTimestamp() public useCurrentTimestampBlock {
+ for (uint256 i = 0; i < _NUM_LOCKERS; i++) {
+ address locker = _lockerHandler.actors(i);
+
+ Lock[] memory locks = _lockStore.getLocks(locker);
+ for (uint256 j = 0; j < locks.length; j++) {
+ Lock memory lock = locks[j];
+ if (lock.amount == 0) {
+ assertEq(veANGLE.balanceOf(locker, lock.timestamp), 0);
+ continue;
+ }
+
+ uint256 balance = veANGLE.balanceOf(locker, lock.timestamp);
+ assertGt(balance, (((lock.amount * (lock.unlockTime - lock.timestamp)) / (365 days * 4)) * 95) / 100);
+ assertLe(balance, (lock.amount * (lock.unlockTime - lock.timestamp)) / (365 days * 4));
+ }
+ }
+ }
+
+ function invariant_RightBalanceAfterTimestamp() public useCurrentTimestampBlock {
+ for (uint256 i = 0; i < _NUM_LOCKERS; i++) {
+ address locker = _lockerHandler.actors(i);
+
+ Lock[] memory locks = _lockStore.getLocks(locker);
+ for (uint256 j = 0; j < locks.length; j++) {
+ Lock memory lock = locks[j];
+ if (lock.amount == 0) {
+ assertEq(veANGLE.balanceOf(locker, lock.timestamp + 1), 0);
+ continue;
+ }
+
+ uint256 balance = veANGLE.balanceOf(locker, lock.timestamp + 1);
+ assertGt(
+ balance,
+ (((lock.amount * (lock.unlockTime - lock.timestamp + 1)) / (365 days * 4)) * 95) / 100
+ );
+ assertLe(balance, (lock.amount * (lock.unlockTime - lock.timestamp + 1)) / (365 days * 4));
+ }
+ }
+ }
+}
diff --git a/test/invariant/actors/BaseActor.t.sol b/test/invariant/actors/BaseActor.t.sol
new file mode 100644
index 0000000..869cdab
--- /dev/null
+++ b/test/invariant/actors/BaseActor.t.sol
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.7;
+
+import { IERC20 } from "oz/token/ERC20/IERC20.sol";
+import { Test, stdMath, StdStorage, stdStorage } from "forge-std/Test.sol";
+
+contract BaseActor is Test {
+ uint256 internal _minWallet = 0; // in base 18
+ uint256 internal _maxWallet = 10 ** (18 + 12); // in base 18
+
+ mapping(bytes32 => uint256) public calls;
+ mapping(address => uint256) public addressToIndex;
+ address[] public actors;
+ uint256 public nbrActor;
+ address internal _currentActor;
+
+ modifier countCall(bytes32 key) {
+ calls[key]++;
+ _;
+ }
+
+ modifier useActor(uint256 actorIndexSeed) {
+ _currentActor = actors[bound(actorIndexSeed, 0, actors.length - 1)];
+ vm.startPrank(_currentActor, _currentActor);
+ _;
+ vm.stopPrank();
+ }
+
+ constructor(uint256 _nbrActor, string memory actorType) {
+ for (uint256 i; i < _nbrActor; ++i) {
+ address actor = address(uint160(uint256(keccak256(abi.encodePacked("actor", actorType, i)))));
+ actors.push(actor);
+ addressToIndex[actor] = i;
+ }
+ nbrActor = _nbrActor;
+ }
+}
diff --git a/test/invariant/actors/Locker.t.sol b/test/invariant/actors/Locker.t.sol
new file mode 100644
index 0000000..593acf9
--- /dev/null
+++ b/test/invariant/actors/Locker.t.sol
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.7;
+
+import "./BaseActor.t.sol";
+import { TimestampStore } from "../stores/TimestampStore.t.sol";
+import { LockStore, Lock } from "../stores/LockStore.t.sol";
+import { IveANGLE } from "../../../contracts/interfaces/IVeANGLE.sol";
+import { console } from "forge-std/console.sol";
+
+contract Locker is BaseActor {
+ IveANGLE public veANGLE;
+ TimestampStore public timestampStore;
+ LockStore public lockStore;
+ IERC20 public angle;
+
+ modifier useCurrentTimestampBlock() {
+ vm.warp(timestampStore.currentTimestamp());
+ vm.roll(timestampStore.currentBlockNumber());
+ _;
+ vm.warp(timestampStore.currentTimestamp());
+ vm.roll(timestampStore.currentBlockNumber());
+ }
+
+ constructor(
+ uint256 _nbrActor,
+ IERC20 _angle,
+ IveANGLE _veANGLE,
+ TimestampStore _timestampStore,
+ LockStore _lockStore
+ ) BaseActor(_nbrActor, "Locker") {
+ timestampStore = _timestampStore;
+ lockStore = _lockStore;
+ angle = _angle;
+ veANGLE = _veANGLE;
+ }
+
+ function createLock(
+ uint256 actorIndex,
+ uint256 amount,
+ uint256 duration
+ ) public useCurrentTimestampBlock useActor(actorIndex) {
+ if (veANGLE.locked__end(_currentActor) != 0) {
+ return;
+ }
+ duration = bound(duration, 365 days * 2, 365 days * 4);
+ amount = bound(amount, 1e18, 100e18);
+
+ deal(address(angle), _currentActor, amount);
+ angle.approve(address(veANGLE), amount);
+
+ veANGLE.create_lock(amount, block.timestamp + duration);
+
+ IveANGLE.LockedBalance memory locked = veANGLE.locked(_currentActor);
+ lockStore.addLock(_currentActor, locked.amount, locked.end, block.timestamp);
+
+ // increase timestamp to avoid lock timestamp collision
+ timestampStore.increaseCurrentTimestamp(10);
+ }
+
+ function withdraw(uint256 actorIndex) public useCurrentTimestampBlock useActor(actorIndex) {
+ if (veANGLE.locked__end(_currentActor) != 0 && veANGLE.locked__end(_currentActor) < block.timestamp) {
+ veANGLE.withdraw();
+ lockStore.addLock(_currentActor, 0, 0, block.timestamp);
+
+ // increase timestamp to avoid lock timestamp collision
+ timestampStore.increaseCurrentTimestamp(10);
+ }
+ }
+
+ function extendLockTime(uint256 actorIndex, uint256 duration) public useCurrentTimestampBlock useActor(actorIndex) {
+ uint256 end = veANGLE.locked__end(_currentActor);
+ if (end == 0 || end < block.timestamp || end + 365 days * 2 > block.timestamp + 365 days * 4) {
+ return;
+ }
+
+ duration = bound(duration, end + 365 days * 2, block.timestamp + 365 days * 4);
+ veANGLE.increase_unlock_time(duration);
+
+ IveANGLE.LockedBalance memory locked = veANGLE.locked(_currentActor);
+
+ Lock memory lastLock = lockStore.getLatestLock(_currentActor);
+ lockStore.addLock(_currentActor, lastLock.amount, locked.end, block.timestamp);
+
+ // increase timestamp to avoid lock timestamp collision
+ timestampStore.increaseCurrentTimestamp(10);
+ }
+
+ function extendLockAmount(uint256 actorIndex, uint256 amount) public useCurrentTimestampBlock useActor(actorIndex) {
+ if (veANGLE.balanceOf(_currentActor) == 0) {
+ return;
+ }
+ amount = bound(amount, 1e18, 100e18);
+
+ deal(address(angle), _currentActor, amount);
+ angle.approve(address(veANGLE), amount);
+ veANGLE.increase_amount(amount);
+
+ Lock memory lastLock = lockStore.getLatestLock(_currentActor);
+ lockStore.addLock(_currentActor, lastLock.amount + amount, lastLock.unlockTime, block.timestamp);
+
+ // increase timestamp to avoid lock timestamp collision
+ timestampStore.increaseCurrentTimestamp(10);
+ }
+}
diff --git a/test/invariant/actors/Param.t.sol b/test/invariant/actors/Param.t.sol
new file mode 100644
index 0000000..dbabcea
--- /dev/null
+++ b/test/invariant/actors/Param.t.sol
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.7;
+
+import "./BaseActor.t.sol";
+import { TimestampStore } from "../stores/TimestampStore.t.sol";
+
+contract Param is BaseActor {
+ TimestampStore public timestampStore;
+
+ constructor(uint256 _nbrActor, TimestampStore _timestampStore) BaseActor(_nbrActor, "Param") {
+ timestampStore = _timestampStore;
+ }
+
+ function wrap(uint256 duration) public {
+ duration = bound(duration, 0, 365 days * 5);
+ timestampStore.increaseCurrentTimestamp(duration);
+ vm.warp(timestampStore.currentTimestamp());
+ vm.roll(timestampStore.currentBlockNumber());
+ }
+}
diff --git a/test/invariant/stores/LockStore.t.sol b/test/invariant/stores/LockStore.t.sol
new file mode 100644
index 0000000..61c7c87
--- /dev/null
+++ b/test/invariant/stores/LockStore.t.sol
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: UNLICENSED
+pragma solidity ^0.8.7;
+
+struct Lock {
+ uint256 amount;
+ uint256 unlockTime;
+ uint256 timestamp;
+}
+
+contract LockStore {
+ mapping(address => Lock[]) public locks;
+
+ constructor() {}
+
+ function addLock(address account, uint256 amount, uint256 unlockTime, uint256 timestamp) external {
+ locks[account].push(Lock(amount, unlockTime, timestamp));
+ }
+
+ function getLatestLock(address account) external view returns (Lock memory) {
+ return locks[account][locks[account].length - 1];
+ }
+
+ function getLocks(address account) external view returns (Lock[] memory) {
+ return locks[account];
+ }
+}
diff --git a/test/invariant/stores/TimestampStore.t.sol b/test/invariant/stores/TimestampStore.t.sol
new file mode 100644
index 0000000..4853212
--- /dev/null
+++ b/test/invariant/stores/TimestampStore.t.sol
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: UNLICENSED
+pragma solidity ^0.8.7;
+
+/// @dev Because Foundry does not commit the state changes between invariant runs, we need to
+/// save the current timestamp in a contract with persistent storage.
+contract TimestampStore {
+ uint256 public currentTimestamp;
+ uint256 public currentBlockNumber;
+
+ constructor() {
+ currentTimestamp = block.timestamp;
+ currentBlockNumber = block.number;
+ }
+
+ function increaseCurrentTimestamp(uint256 timeJump) external {
+ currentTimestamp += timeJump;
+ currentBlockNumber += 1;
+ }
+
+ function increaseCurrentBlockNumber(uint256 blockJump) external {
+ currentTimestamp += 1;
+ currentBlockNumber += blockJump;
+ }
+}
diff --git a/test/unit/.gitkeep b/test/unit/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/test/unit/BalanceOf.t.sol b/test/unit/BalanceOf.t.sol
new file mode 100644
index 0000000..e1d1d6f
--- /dev/null
+++ b/test/unit/BalanceOf.t.sol
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.7;
+
+import { Fixture, IveANGLE } from "../Fixture.t.sol";
+import { console } from "forge-std/console.sol";
+
+contract BalanceOf is Fixture {
+ function test_balanceOf_LocksAfterTimestamp() external {
+ uint256 timestamp = block.timestamp + 365 days * 2;
+ uint256 oldTimestamp = block.timestamp;
+ uint256 amount = 10e18;
+
+ deal(address(Angle), alice, amount);
+
+ vm.startPrank(alice, alice);
+ Angle.approve(address(veANGLE), amount);
+ veANGLE.create_lock(amount, timestamp);
+ vm.stopPrank();
+
+ vm.warp(block.timestamp + 200 days);
+
+ assertEq(veANGLE.balanceOf(alice, oldTimestamp - 1), 0);
+ }
+
+ function test_balanceOf_ExtendDate() external {
+ uint256 timestamp = block.timestamp + 365 days * 2;
+ uint256 oldTimestamp = block.timestamp;
+ uint256 amount = 10e18;
+
+ deal(address(Angle), alice, amount);
+
+ vm.startPrank(alice, alice);
+ Angle.approve(address(veANGLE), amount);
+ veANGLE.create_lock(amount, timestamp);
+ vm.stopPrank();
+
+ vm.warp(block.timestamp + 200 days);
+
+ vm.prank(alice, alice);
+ veANGLE.increase_unlock_time(block.timestamp + 4 * 365 days);
+
+ assertGt(veANGLE.balanceOf(alice, block.timestamp), ((amount * 10000) * 95) / 1000000);
+ assertLt(veANGLE.balanceOf(alice, block.timestamp), amount);
+
+ assertGt(veANGLE.balanceOf(alice, oldTimestamp), ((amount * 10000) * 47) / 1000000);
+ assertLt(veANGLE.balanceOf(alice, oldTimestamp), amount);
+ }
+
+ function test_balanceOf_ExtendAmount() external {
+ uint256 timestamp = block.timestamp + 365 days * 2;
+ uint256 oldTimestamp = block.timestamp;
+ uint256 amount = 10e18;
+ uint256 amount2 = 10e18;
+
+ deal(address(Angle), alice, amount + amount2);
+
+ vm.startPrank(alice, alice);
+ Angle.approve(address(veANGLE), amount);
+ veANGLE.create_lock(amount, timestamp);
+ vm.stopPrank();
+
+ vm.warp(block.timestamp + 365 days);
+
+ vm.startPrank(alice, alice);
+ Angle.approve(address(veANGLE), amount2);
+ veANGLE.increase_amount(amount2);
+ vm.stopPrank();
+
+ assertGt(veANGLE.balanceOf(alice, block.timestamp), (((amount + amount2) * 10000) * 22) / 1000000);
+ assertLt(veANGLE.balanceOf(alice, block.timestamp), amount + amount2);
+
+ assertGt(veANGLE.balanceOf(alice, oldTimestamp), ((amount * 10000) * 47) / 1000000);
+ assertLt(veANGLE.balanceOf(alice, oldTimestamp), amount);
+ }
+
+ function test_balanceOf_LocksBeforeTimestamp() external {
+ uint256 timestamp = block.timestamp + 365 days * 2;
+ uint256 oldTimestamp = block.timestamp;
+ uint256 amount = 10e18;
+
+ deal(address(Angle), alice, amount);
+
+ vm.startPrank(alice, alice);
+ Angle.approve(address(veANGLE), amount);
+ veANGLE.create_lock(amount, timestamp);
+ vm.stopPrank();
+
+ assertGt(veANGLE.balanceOf(alice, block.timestamp), ((amount * 10000) * 47) / 1000000);
+ assertLt(veANGLE.balanceOf(alice, block.timestamp), amount);
+ }
+
+ function test_balanceOf_MultipleLocks() external {
+ uint256 timestamp = block.timestamp + 365 days * 2;
+ uint256 oldTimestamp = block.timestamp;
+ uint256 amount = 10e18;
+ uint256 amount2 = 100e18;
+
+ deal(address(Angle), alice, amount);
+
+ vm.startPrank(alice, alice);
+ Angle.approve(address(veANGLE), amount);
+ veANGLE.create_lock(amount, timestamp);
+ vm.stopPrank();
+
+ vm.warp(block.timestamp + 365 days * 2 + 1);
+
+ deal(address(Angle), alice, amount2);
+
+ vm.startPrank(alice, alice);
+ veANGLE.withdraw();
+ Angle.approve(address(veANGLE), amount2);
+ veANGLE.create_lock(amount2, block.timestamp + 365 days * 2);
+ vm.stopPrank();
+
+ assertGt(veANGLE.balanceOf(alice, block.timestamp), ((amount2 * 10000) * 47) / 1000000);
+ assertLt(veANGLE.balanceOf(alice, block.timestamp), amount2);
+
+ assertGt(veANGLE.balanceOf(alice, oldTimestamp), ((amount * 10000) * 47) / 1000000);
+ assertLt(veANGLE.balanceOf(alice, oldTimestamp), amount);
+ }
+}
diff --git a/test/unit/EmergencyWithdrawal.t.sol b/test/unit/EmergencyWithdrawal.t.sol
new file mode 100644
index 0000000..7fcf1dd
--- /dev/null
+++ b/test/unit/EmergencyWithdrawal.t.sol
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.7;
+
+import { Fixture, IveANGLE } from "../Fixture.t.sol";
+
+contract EmergencyWithdrawal is Fixture {
+ function test_emergencyWithdrawal_Normal() external {
+ assertEq(veANGLE.emergency_withdrawal(), false);
+
+ vm.prank(admin);
+ veANGLE.set_emergency_withdrawal();
+
+ assertEq(veANGLE.emergency_withdrawal(), true);
+ }
+
+ function test_emergencyWithdrawal_checkpoint() external {
+ vm.prank(admin);
+ veANGLE.set_emergency_withdrawal();
+
+ vm.expectRevert("Emergency withdrawal enabled");
+ veANGLE.checkpoint();
+ }
+
+ function test_emergencyWithdrawal_create_lock() external {
+ vm.prank(admin);
+ veANGLE.set_emergency_withdrawal();
+
+ vm.expectRevert("Emergency withdrawal enabled");
+ veANGLE.create_lock(10e18, block.timestamp + 365 days);
+ }
+
+ function test_emergencyWithdrawal_increase_amount() external {
+ vm.prank(admin);
+ veANGLE.set_emergency_withdrawal();
+
+ vm.expectRevert("Emergency withdrawal enabled");
+ veANGLE.increase_amount(0);
+ }
+
+ function test_emergencyWithdrawal_increase_unlock_time() external {
+ vm.prank(admin);
+ veANGLE.set_emergency_withdrawal();
+
+ vm.expectRevert("Emergency withdrawal enabled");
+ veANGLE.increase_unlock_time(block.timestamp + 365 days);
+ }
+
+ function test_emergencyWithdrawal_withdraw() external {
+ vm.prank(admin);
+ veANGLE.set_emergency_withdrawal();
+
+ vm.expectRevert("Emergency withdrawal enabled");
+ veANGLE.withdraw();
+ }
+
+ function test_emergencyWithdrawal_deposit_for() external {
+ vm.prank(admin);
+ veANGLE.set_emergency_withdrawal();
+
+ vm.expectRevert("Emergency withdrawal enabled");
+ veANGLE.deposit_for(alice, 10e18);
+ }
+
+ function test_emergencyWithdrawal_SingleLock() external {
+ deal(address(Angle), alice, 10e18);
+
+ vm.startPrank(alice, alice);
+ Angle.approve(address(veANGLE), 10e18);
+ veANGLE.create_lock(10e18, block.timestamp + 365 days);
+ vm.stopPrank();
+
+ assertEq(Angle.balanceOf(alice), 0);
+
+ vm.prank(admin);
+ veANGLE.set_emergency_withdrawal();
+
+ vm.prank(alice, alice);
+ veANGLE.withdraw_fast();
+
+ assertEq(Angle.balanceOf(alice), 10e18);
+ }
+
+ function test_emergencyWithdrawal_AfterLockExpired() external {
+ deal(address(Angle), alice, 10e18);
+
+ vm.startPrank(alice, alice);
+ Angle.approve(address(veANGLE), 10e18);
+ veANGLE.create_lock(10e18, block.timestamp + 365 days);
+ vm.stopPrank();
+
+ assertEq(Angle.balanceOf(alice), 0);
+
+ vm.prank(admin);
+ veANGLE.set_emergency_withdrawal();
+
+ vm.warp(block.timestamp + 365 days + 1);
+
+ vm.prank(alice, alice);
+ veANGLE.withdraw_fast();
+
+ assertEq(Angle.balanceOf(alice), 10e18);
+ }
+
+ function test_emergencyWithdrawal_MultipleLocks() external {
+ deal(address(Angle), alice, 10e18);
+ deal(address(Angle), bob, 20e18);
+
+ vm.startPrank(alice, alice);
+ Angle.approve(address(veANGLE), 10e18);
+ veANGLE.create_lock(10e18, block.timestamp + 365 days * 4);
+ vm.stopPrank();
+
+ vm.warp(block.timestamp + 365 days);
+
+ vm.startPrank(bob, bob);
+ Angle.approve(address(veANGLE), 20e18);
+ veANGLE.create_lock(20e18, block.timestamp + 365 days * 2);
+ vm.stopPrank();
+
+ assertEq(Angle.balanceOf(alice), 0);
+ assertEq(Angle.balanceOf(bob), 0);
+
+ vm.prank(admin);
+ veANGLE.set_emergency_withdrawal();
+
+ vm.prank(alice, alice);
+ veANGLE.withdraw_fast();
+
+ assertEq(Angle.balanceOf(alice), 10e18);
+
+ vm.warp(block.timestamp + 365 days);
+
+ vm.prank(bob, bob);
+ veANGLE.withdraw_fast();
+
+ assertEq(Angle.balanceOf(bob), 20e18);
+ }
+
+ function test_emergencyWithdrawal_CannotWithdrawTwice() external {
+ deal(address(Angle), alice, 10e18);
+
+ vm.startPrank(alice, alice);
+ Angle.approve(address(veANGLE), 10e18);
+ veANGLE.create_lock(10e18, block.timestamp + 365 days);
+ vm.stopPrank();
+
+ assertEq(Angle.balanceOf(alice), 0);
+
+ vm.prank(admin);
+ veANGLE.set_emergency_withdrawal();
+
+ vm.prank(alice, alice);
+ veANGLE.withdraw_fast();
+
+ assertEq(Angle.balanceOf(alice), 10e18);
+
+ vm.prank(alice, alice);
+ veANGLE.withdraw_fast();
+
+ assertEq(Angle.balanceOf(alice), 10e18);
+ }
+
+ function test_emergencyWithdrawal_CannotWithdrawWhenNoEmergency() external {
+ deal(address(Angle), alice, 20e18);
+
+ vm.startPrank(alice, alice);
+ Angle.approve(address(veANGLE), 20e18);
+ veANGLE.create_lock(10e18, block.timestamp + 365 days);
+ vm.stopPrank();
+
+ vm.expectRevert("Emergency withdrawal not enabled");
+ veANGLE.withdraw_fast();
+ }
+}
diff --git a/yarn.lock b/yarn.lock
index 54f44d1..1a6fa94 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,6 +2,44 @@
# yarn lockfile v1
+"@angleprotocol/sdk@^0.38.0":
+ version "0.38.0"
+ resolved "https://npm.pkg.github.com/download/@angleprotocol/sdk/0.38.0/c8050577a3f844b3e4713bef2f0628eba7e522fd#c8050577a3f844b3e4713bef2f0628eba7e522fd"
+ integrity sha512-mufd2bhCSyWKyzf45HsIz6rhw2rS1nyXnp2FyvDDvXpk6xSGYIClF870FleCd9vCVBrf10tz8oDXY7y80V3CMg==
+ dependencies:
+ "@apollo/client" "^3.7.17"
+ "@typechain/ethers-v5" "^10.0.0"
+ "@types/lodash" "^4.14.180"
+ ethers "^5.6.4"
+ graphql "^15.7.1"
+ graphql-request "^3.6.1"
+ jsbi "^4.3.0"
+ keccak256 "^1.0.6"
+ lodash "^4.17.21"
+ merkletreejs "^0.3.10"
+ tiny-invariant "^1.1.0"
+ typechain "^8.3.2"
+
+"@apollo/client@^3.7.17":
+ version "3.9.9"
+ resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.9.9.tgz#38f983a1ad24e2687abfced0a9c1c3bef8d32616"
+ integrity sha512-/sMecU/M0WK9knrguts1lSLV8xFKzIgOMVb4mi6MOxgJXjliDB8PvOtmXhTqh2cVMMR4TzXgOnb+af/690zlQw==
+ dependencies:
+ "@graphql-typed-document-node/core" "^3.1.1"
+ "@wry/caches" "^1.0.0"
+ "@wry/equality" "^0.5.6"
+ "@wry/trie" "^0.5.0"
+ graphql-tag "^2.12.6"
+ hoist-non-react-statics "^3.3.2"
+ optimism "^0.18.0"
+ prop-types "^15.7.2"
+ rehackt "0.0.6"
+ response-iterator "^0.2.6"
+ symbol-observable "^4.0.0"
+ ts-invariant "^0.10.3"
+ tslib "^2.3.0"
+ zen-observable-ts "^1.2.5"
+
"@babel/code-frame@^7.0.0":
version "7.22.13"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e"
@@ -24,6 +62,401 @@
chalk "^2.4.2"
js-tokens "^4.0.0"
+"@ethereumjs/rlp@^4.0.1":
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-4.0.1.tgz#626fabfd9081baab3d0a3074b0c7ecaf674aaa41"
+ integrity sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==
+
+"@ethereumjs/util@^8.1.0":
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-8.1.0.tgz#299df97fb6b034e0577ce9f94c7d9d1004409ed4"
+ integrity sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==
+ dependencies:
+ "@ethereumjs/rlp" "^4.0.1"
+ ethereum-cryptography "^2.0.0"
+ micro-ftch "^0.3.1"
+
+"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449"
+ integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==
+ dependencies:
+ "@ethersproject/address" "^5.7.0"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/constants" "^5.7.0"
+ "@ethersproject/hash" "^5.7.0"
+ "@ethersproject/keccak256" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/strings" "^5.7.0"
+
+"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef"
+ integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==
+ dependencies:
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/networks" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/transactions" "^5.7.0"
+ "@ethersproject/web" "^5.7.0"
+
+"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2"
+ integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==
+ dependencies:
+ "@ethersproject/abstract-provider" "^5.7.0"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+
+"@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37"
+ integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==
+ dependencies:
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/keccak256" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/rlp" "^5.7.0"
+
+"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c"
+ integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+
+"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b"
+ integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+
+"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2"
+ integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ bn.js "^5.2.1"
+
+"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d"
+ integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==
+ dependencies:
+ "@ethersproject/logger" "^5.7.0"
+
+"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e"
+ integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==
+ dependencies:
+ "@ethersproject/bignumber" "^5.7.0"
+
+"@ethersproject/contracts@5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e"
+ integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==
+ dependencies:
+ "@ethersproject/abi" "^5.7.0"
+ "@ethersproject/abstract-provider" "^5.7.0"
+ "@ethersproject/abstract-signer" "^5.7.0"
+ "@ethersproject/address" "^5.7.0"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/constants" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/transactions" "^5.7.0"
+
+"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7"
+ integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==
+ dependencies:
+ "@ethersproject/abstract-signer" "^5.7.0"
+ "@ethersproject/address" "^5.7.0"
+ "@ethersproject/base64" "^5.7.0"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/keccak256" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/strings" "^5.7.0"
+
+"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf"
+ integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==
+ dependencies:
+ "@ethersproject/abstract-signer" "^5.7.0"
+ "@ethersproject/basex" "^5.7.0"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/pbkdf2" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/sha2" "^5.7.0"
+ "@ethersproject/signing-key" "^5.7.0"
+ "@ethersproject/strings" "^5.7.0"
+ "@ethersproject/transactions" "^5.7.0"
+ "@ethersproject/wordlists" "^5.7.0"
+
+"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360"
+ integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==
+ dependencies:
+ "@ethersproject/abstract-signer" "^5.7.0"
+ "@ethersproject/address" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/hdnode" "^5.7.0"
+ "@ethersproject/keccak256" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/pbkdf2" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/random" "^5.7.0"
+ "@ethersproject/strings" "^5.7.0"
+ "@ethersproject/transactions" "^5.7.0"
+ aes-js "3.0.0"
+ scrypt-js "3.0.1"
+
+"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a"
+ integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+ js-sha3 "0.8.0"
+
+"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892"
+ integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==
+
+"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0":
+ version "5.7.1"
+ resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6"
+ integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==
+ dependencies:
+ "@ethersproject/logger" "^5.7.0"
+
+"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102"
+ integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/sha2" "^5.7.0"
+
+"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30"
+ integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==
+ dependencies:
+ "@ethersproject/logger" "^5.7.0"
+
+"@ethersproject/providers@5.7.2":
+ version "5.7.2"
+ resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb"
+ integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==
+ dependencies:
+ "@ethersproject/abstract-provider" "^5.7.0"
+ "@ethersproject/abstract-signer" "^5.7.0"
+ "@ethersproject/address" "^5.7.0"
+ "@ethersproject/base64" "^5.7.0"
+ "@ethersproject/basex" "^5.7.0"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/constants" "^5.7.0"
+ "@ethersproject/hash" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/networks" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/random" "^5.7.0"
+ "@ethersproject/rlp" "^5.7.0"
+ "@ethersproject/sha2" "^5.7.0"
+ "@ethersproject/strings" "^5.7.0"
+ "@ethersproject/transactions" "^5.7.0"
+ "@ethersproject/web" "^5.7.0"
+ bech32 "1.1.4"
+ ws "7.4.6"
+
+"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c"
+ integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+
+"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304"
+ integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+
+"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb"
+ integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ hash.js "1.1.7"
+
+"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3"
+ integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ bn.js "^5.2.1"
+ elliptic "6.5.4"
+ hash.js "1.1.7"
+
+"@ethersproject/solidity@5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8"
+ integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==
+ dependencies:
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/keccak256" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/sha2" "^5.7.0"
+ "@ethersproject/strings" "^5.7.0"
+
+"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2"
+ integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/constants" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+
+"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b"
+ integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==
+ dependencies:
+ "@ethersproject/address" "^5.7.0"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/constants" "^5.7.0"
+ "@ethersproject/keccak256" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/rlp" "^5.7.0"
+ "@ethersproject/signing-key" "^5.7.0"
+
+"@ethersproject/units@5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1"
+ integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==
+ dependencies:
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/constants" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+
+"@ethersproject/wallet@5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d"
+ integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==
+ dependencies:
+ "@ethersproject/abstract-provider" "^5.7.0"
+ "@ethersproject/abstract-signer" "^5.7.0"
+ "@ethersproject/address" "^5.7.0"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/hash" "^5.7.0"
+ "@ethersproject/hdnode" "^5.7.0"
+ "@ethersproject/json-wallets" "^5.7.0"
+ "@ethersproject/keccak256" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/random" "^5.7.0"
+ "@ethersproject/signing-key" "^5.7.0"
+ "@ethersproject/transactions" "^5.7.0"
+ "@ethersproject/wordlists" "^5.7.0"
+
+"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0":
+ version "5.7.1"
+ resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae"
+ integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==
+ dependencies:
+ "@ethersproject/base64" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/strings" "^5.7.0"
+
+"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5"
+ integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/hash" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/strings" "^5.7.0"
+
+"@graphql-typed-document-node/core@^3.1.1":
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861"
+ integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==
+
+"@noble/curves@1.3.0", "@noble/curves@~1.3.0":
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.3.0.tgz#01be46da4fd195822dab821e72f71bf4aeec635e"
+ integrity sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==
+ dependencies:
+ "@noble/hashes" "1.3.3"
+
+"@noble/hashes@1.3.3", "@noble/hashes@~1.3.2":
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699"
+ integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==
+
+"@scure/base@~1.1.4":
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.6.tgz#8ce5d304b436e4c84f896e0550c83e4d88cb917d"
+ integrity sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==
+
+"@scure/bip32@1.3.3":
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.3.tgz#a9624991dc8767087c57999a5d79488f48eae6c8"
+ integrity sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==
+ dependencies:
+ "@noble/curves" "~1.3.0"
+ "@noble/hashes" "~1.3.2"
+ "@scure/base" "~1.1.4"
+
+"@scure/bip39@1.2.2":
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.2.tgz#f3426813f4ced11a47489cbcf7294aa963966527"
+ integrity sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==
+ dependencies:
+ "@noble/hashes" "~1.3.2"
+ "@scure/base" "~1.1.4"
+
"@solidity-parser/parser@^0.16.0":
version "0.16.1"
resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.16.1.tgz#f7c8a686974e1536da0105466c4db6727311253c"
@@ -31,6 +464,64 @@
dependencies:
antlr4ts "^0.5.0-alpha.4"
+"@typechain/ethers-v5@^10.0.0":
+ version "10.2.1"
+ resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-10.2.1.tgz#50241e6957683281ecfa03fb5a6724d8a3ce2391"
+ integrity sha512-n3tQmCZjRE6IU4h6lqUGiQ1j866n5MTCBJreNEHHVWXa2u9GJTaeYyU1/k+1qLutkyw+sS6VAN+AbeiTqsxd/A==
+ dependencies:
+ lodash "^4.17.15"
+ ts-essentials "^7.0.1"
+
+"@types/lodash@^4.14.180":
+ version "4.17.0"
+ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.0.tgz#d774355e41f372d5350a4d0714abb48194a489c3"
+ integrity sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==
+
+"@types/prettier@^2.1.1":
+ version "2.7.3"
+ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f"
+ integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==
+
+"@wry/caches@^1.0.0":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@wry/caches/-/caches-1.0.1.tgz#8641fd3b6e09230b86ce8b93558d44cf1ece7e52"
+ integrity sha512-bXuaUNLVVkD20wcGBWRyo7j9N3TxePEWFZj2Y+r9OoUzfqmavM84+mFykRicNsBqatba5JLay1t48wxaXaWnlA==
+ dependencies:
+ tslib "^2.3.0"
+
+"@wry/context@^0.7.0":
+ version "0.7.4"
+ resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.7.4.tgz#e32d750fa075955c4ab2cfb8c48095e1d42d5990"
+ integrity sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ==
+ dependencies:
+ tslib "^2.3.0"
+
+"@wry/equality@^0.5.6":
+ version "0.5.7"
+ resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.5.7.tgz#72ec1a73760943d439d56b7b1e9985aec5d497bb"
+ integrity sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw==
+ dependencies:
+ tslib "^2.3.0"
+
+"@wry/trie@^0.4.3":
+ version "0.4.3"
+ resolved "https://registry.yarnpkg.com/@wry/trie/-/trie-0.4.3.tgz#077d52c22365871bf3ffcbab8e95cb8bc5689af4"
+ integrity sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w==
+ dependencies:
+ tslib "^2.3.0"
+
+"@wry/trie@^0.5.0":
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/@wry/trie/-/trie-0.5.0.tgz#11e783f3a53f6e4cd1d42d2d1323f5bc3fa99c94"
+ integrity sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA==
+ dependencies:
+ tslib "^2.3.0"
+
+aes-js@3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d"
+ integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==
+
ajv@^6.12.6:
version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
@@ -85,6 +576,16 @@ argparse@^2.0.1:
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
+array-back@^3.0.1, array-back@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0"
+ integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==
+
+array-back@^4.0.1, array-back@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e"
+ integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==
+
ast-parents@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/ast-parents/-/ast-parents-0.0.1.tgz#508fd0f05d0c48775d9eccda2e174423261e8dd3"
@@ -95,11 +596,54 @@ astral-regex@^2.0.0:
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
+asynckit@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+ integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
+
balanced-match@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+base64-js@^1.3.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
+ integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
+
+bech32@1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9"
+ integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==
+
+bignumber.js@^9.0.1:
+ version "9.1.2"
+ resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c"
+ integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==
+
+bn.js@4.11.6:
+ version "4.11.6"
+ resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215"
+ integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==
+
+bn.js@^4.11.9:
+ version "4.12.0"
+ resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88"
+ integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==
+
+bn.js@^5.2.0, bn.js@^5.2.1:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70"
+ integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==
+
+brace-expansion@^1.1.7:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+ integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
brace-expansion@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
@@ -107,6 +651,24 @@ brace-expansion@^2.0.1:
dependencies:
balanced-match "^1.0.0"
+brorand@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
+ integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==
+
+buffer-reverse@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/buffer-reverse/-/buffer-reverse-1.0.1.tgz#49283c8efa6f901bc01fa3304d06027971ae2f60"
+ integrity sha512-M87YIUBsZ6N924W57vDwT/aOu8hw7ZgdByz6ijksLjmHJELBASmYTTlNHRgjE+pTsT9oJXGaDSgqqwfdHotDUg==
+
+buffer@^6.0.3:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
+ integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==
+ dependencies:
+ base64-js "^1.3.1"
+ ieee754 "^1.2.1"
+
callsites@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
@@ -121,7 +683,7 @@ chalk@^2.4.2:
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
-chalk@^4.1.2:
+chalk@^4.1.0, chalk@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
@@ -153,11 +715,43 @@ color-name@~1.1.4:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+combined-stream@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
+ integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+ dependencies:
+ delayed-stream "~1.0.0"
+
+command-line-args@^5.1.1:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e"
+ integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==
+ dependencies:
+ array-back "^3.1.0"
+ find-replace "^3.0.0"
+ lodash.camelcase "^4.3.0"
+ typical "^4.0.0"
+
+command-line-usage@^6.1.0:
+ version "6.1.3"
+ resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.3.tgz#428fa5acde6a838779dfa30e44686f4b6761d957"
+ integrity sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==
+ dependencies:
+ array-back "^4.0.2"
+ chalk "^2.4.2"
+ table-layout "^1.0.2"
+ typical "^5.2.0"
+
commander@^10.0.0:
version "10.0.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06"
integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+ integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
+
cosmiconfig@^8.0.0:
version "8.3.6"
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3"
@@ -168,6 +762,48 @@ cosmiconfig@^8.0.0:
parse-json "^5.2.0"
path-type "^4.0.0"
+cross-fetch@^3.0.6:
+ version "3.1.8"
+ resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82"
+ integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==
+ dependencies:
+ node-fetch "^2.6.12"
+
+crypto-js@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631"
+ integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==
+
+debug@^4.3.1:
+ version "4.3.4"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
+ integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
+ dependencies:
+ ms "2.1.2"
+
+deep-extend@~0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
+ integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
+
+delayed-stream@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+ integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
+
+elliptic@6.5.4:
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
+ integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==
+ dependencies:
+ bn.js "^4.11.9"
+ brorand "^1.1.0"
+ hash.js "^1.0.0"
+ hmac-drbg "^1.0.1"
+ inherits "^2.0.4"
+ minimalistic-assert "^1.0.1"
+ minimalistic-crypto-utils "^1.0.1"
+
emoji-regex@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
@@ -185,6 +821,72 @@ escape-string-regexp@^1.0.5:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
+ethereum-bloom-filters@^1.0.6:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz#3ca07f4aed698e75bd134584850260246a5fed8a"
+ integrity sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA==
+ dependencies:
+ js-sha3 "^0.8.0"
+
+ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.1.2:
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz#1352270ed3b339fe25af5ceeadcf1b9c8e30768a"
+ integrity sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==
+ dependencies:
+ "@noble/curves" "1.3.0"
+ "@noble/hashes" "1.3.3"
+ "@scure/bip32" "1.3.3"
+ "@scure/bip39" "1.2.2"
+
+ethers@^5.6.4:
+ version "5.7.2"
+ resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e"
+ integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==
+ dependencies:
+ "@ethersproject/abi" "5.7.0"
+ "@ethersproject/abstract-provider" "5.7.0"
+ "@ethersproject/abstract-signer" "5.7.0"
+ "@ethersproject/address" "5.7.0"
+ "@ethersproject/base64" "5.7.0"
+ "@ethersproject/basex" "5.7.0"
+ "@ethersproject/bignumber" "5.7.0"
+ "@ethersproject/bytes" "5.7.0"
+ "@ethersproject/constants" "5.7.0"
+ "@ethersproject/contracts" "5.7.0"
+ "@ethersproject/hash" "5.7.0"
+ "@ethersproject/hdnode" "5.7.0"
+ "@ethersproject/json-wallets" "5.7.0"
+ "@ethersproject/keccak256" "5.7.0"
+ "@ethersproject/logger" "5.7.0"
+ "@ethersproject/networks" "5.7.1"
+ "@ethersproject/pbkdf2" "5.7.0"
+ "@ethersproject/properties" "5.7.0"
+ "@ethersproject/providers" "5.7.2"
+ "@ethersproject/random" "5.7.0"
+ "@ethersproject/rlp" "5.7.0"
+ "@ethersproject/sha2" "5.7.0"
+ "@ethersproject/signing-key" "5.7.0"
+ "@ethersproject/solidity" "5.7.0"
+ "@ethersproject/strings" "5.7.0"
+ "@ethersproject/transactions" "5.7.0"
+ "@ethersproject/units" "5.7.0"
+ "@ethersproject/wallet" "5.7.0"
+ "@ethersproject/web" "5.7.1"
+ "@ethersproject/wordlists" "5.7.0"
+
+ethjs-unit@0.1.6:
+ version "0.1.6"
+ resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699"
+ integrity sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==
+ dependencies:
+ bn.js "4.11.6"
+ number-to-bn "1.7.0"
+
+extract-files@^9.0.0:
+ version "9.0.0"
+ resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-9.0.0.tgz#8a7744f2437f81f5ed3250ed9f1550de902fe54a"
+ integrity sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==
+
fast-deep-equal@^3.1.1:
version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
@@ -200,11 +902,48 @@ fast-json-stable-stringify@^2.0.0:
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
+find-replace@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38"
+ integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==
+ dependencies:
+ array-back "^3.0.1"
+
+form-data@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f"
+ integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.8"
+ mime-types "^2.1.12"
+
+fs-extra@^7.0.0:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9"
+ integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==
+ dependencies:
+ graceful-fs "^4.1.2"
+ jsonfile "^4.0.0"
+ universalify "^0.1.0"
+
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
+glob@7.1.7:
+ version "7.1.7"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
+ integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.0.4"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
glob@^8.0.3:
version "8.1.0"
resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e"
@@ -216,6 +955,32 @@ glob@^8.0.3:
minimatch "^5.0.1"
once "^1.3.0"
+graceful-fs@^4.1.2, graceful-fs@^4.1.6:
+ version "4.2.11"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
+ integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
+
+graphql-request@^3.6.1:
+ version "3.7.0"
+ resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-3.7.0.tgz#c7406e537084f8b9788541e3e6704340ca13055b"
+ integrity sha512-dw5PxHCgBneN2DDNqpWu8QkbbJ07oOziy8z+bK/TAXufsOLaETuVO4GkXrbs0WjhdKhBMN3BkpN/RIvUHkmNUQ==
+ dependencies:
+ cross-fetch "^3.0.6"
+ extract-files "^9.0.0"
+ form-data "^3.0.0"
+
+graphql-tag@^2.12.6:
+ version "2.12.6"
+ resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.6.tgz#d441a569c1d2537ef10ca3d1633b48725329b5f1"
+ integrity sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==
+ dependencies:
+ tslib "^2.1.0"
+
+graphql@^15.7.1:
+ version "15.8.0"
+ resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.8.0.tgz#33410e96b012fa3bdb1091cc99a94769db212b38"
+ integrity sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==
+
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
@@ -226,6 +991,35 @@ has-flag@^4.0.0:
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3:
+ version "1.1.7"
+ resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42"
+ integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==
+ dependencies:
+ inherits "^2.0.3"
+ minimalistic-assert "^1.0.1"
+
+hmac-drbg@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
+ integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==
+ dependencies:
+ hash.js "^1.0.3"
+ minimalistic-assert "^1.0.0"
+ minimalistic-crypto-utils "^1.0.1"
+
+hoist-non-react-statics@^3.3.2:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
+ integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
+ dependencies:
+ react-is "^16.7.0"
+
+ieee754@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
+ integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
+
ignore@^5.2.4:
version "5.2.4"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324"
@@ -247,7 +1041,7 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
-inherits@2:
+inherits@2, inherits@^2.0.3, inherits@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@@ -262,7 +1056,17 @@ is-fullwidth-code-point@^3.0.0:
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
-js-tokens@^4.0.0:
+is-hex-prefixed@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554"
+ integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==
+
+js-sha3@0.8.0, js-sha3@^0.8.0:
+ version "0.8.0"
+ resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"
+ integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==
+
+"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
@@ -274,6 +1078,11 @@ js-yaml@^4.1.0:
dependencies:
argparse "^2.0.1"
+jsbi@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-4.3.0.tgz#b54ee074fb6fcbc00619559305c8f7e912b04741"
+ integrity sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g==
+
json-parse-even-better-errors@^2.3.0:
version "2.3.1"
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
@@ -289,21 +1098,58 @@ json-schema-traverse@^1.0.0:
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
+jsonfile@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
+ integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==
+ optionalDependencies:
+ graceful-fs "^4.1.6"
+
+keccak256@^1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/keccak256/-/keccak256-1.0.6.tgz#dd32fb771558fed51ce4e45a035ae7515573da58"
+ integrity sha512-8GLiM01PkdJVGUhR1e6M/AvWnSqYS0HaERI+K/QtStGDGlSTx2B1zTqZk4Zlqu5TxHJNTxWAdP9Y+WI50OApUw==
+ dependencies:
+ bn.js "^5.2.0"
+ buffer "^6.0.3"
+ keccak "^3.0.2"
+
+keccak@^3.0.2:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.4.tgz#edc09b89e633c0549da444432ecf062ffadee86d"
+ integrity sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==
+ dependencies:
+ node-addon-api "^2.0.0"
+ node-gyp-build "^4.2.0"
+ readable-stream "^3.6.0"
+
lines-and-columns@^1.1.6:
version "1.2.4"
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
+lodash.camelcase@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
+ integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==
+
lodash.truncate@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==
-lodash@^4.17.21:
+lodash@^4.17.15, lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
+loose-envify@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
+ integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
+ dependencies:
+ js-tokens "^3.0.0 || ^4.0.0"
+
lru-cache@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
@@ -311,6 +1157,51 @@ lru-cache@^6.0.0:
dependencies:
yallist "^4.0.0"
+merkletreejs@^0.3.10:
+ version "0.3.11"
+ resolved "https://registry.yarnpkg.com/merkletreejs/-/merkletreejs-0.3.11.tgz#e0de05c3ca1fd368de05a12cb8efb954ef6fc04f"
+ integrity sha512-LJKTl4iVNTndhL+3Uz/tfkjD0klIWsHlUzgtuNnNrsf7bAlXR30m+xYB7lHr5Z/l6e/yAIsr26Dabx6Buo4VGQ==
+ dependencies:
+ bignumber.js "^9.0.1"
+ buffer-reverse "^1.0.1"
+ crypto-js "^4.2.0"
+ treeify "^1.1.0"
+ web3-utils "^1.3.4"
+
+micro-ftch@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/micro-ftch/-/micro-ftch-0.3.1.tgz#6cb83388de4c1f279a034fb0cf96dfc050853c5f"
+ integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==
+
+mime-db@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
+ integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
+
+mime-types@^2.1.12:
+ version "2.1.35"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
+ integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
+ dependencies:
+ mime-db "1.52.0"
+
+minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
+ integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
+
+minimalistic-crypto-utils@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
+ integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==
+
+minimatch@^3.0.4:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
+ integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
+ dependencies:
+ brace-expansion "^1.1.7"
+
minimatch@^5.0.1:
version "5.1.6"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96"
@@ -318,6 +1209,46 @@ minimatch@^5.0.1:
dependencies:
brace-expansion "^2.0.1"
+mkdirp@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
+ integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
+
+ms@2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
+ integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
+node-addon-api@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32"
+ integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==
+
+node-fetch@^2.6.12:
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
+ integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
+ dependencies:
+ whatwg-url "^5.0.0"
+
+node-gyp-build@^4.2.0:
+ version "4.8.0"
+ resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.0.tgz#3fee9c1731df4581a3f9ead74664369ff00d26dd"
+ integrity sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==
+
+number-to-bn@1.7.0:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0"
+ integrity sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==
+ dependencies:
+ bn.js "4.11.6"
+ strip-hex-prefix "1.0.0"
+
+object-assign@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
+ integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
+
once@^1.3.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@@ -325,6 +1256,16 @@ once@^1.3.0:
dependencies:
wrappy "1"
+optimism@^0.18.0:
+ version "0.18.0"
+ resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.18.0.tgz#e7bb38b24715f3fdad8a9a7fc18e999144bbfa63"
+ integrity sha512-tGn8+REwLRNFnb9WmcY5IfpOqeX2kpaYJ1s6Ae3mn12AeydLkR3j+jSCmVQFoXqU8D41PAJ1RG1rCRNWmNZVmQ==
+ dependencies:
+ "@wry/caches" "^1.0.0"
+ "@wry/context" "^0.7.0"
+ "@wry/trie" "^0.4.3"
+ tslib "^2.3.0"
+
parent-module@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
@@ -342,6 +1283,11 @@ parse-json@^5.2.0:
json-parse-even-better-errors "^2.3.0"
lines-and-columns "^1.1.6"
+path-is-absolute@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+ integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
+
path-type@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
@@ -368,16 +1314,56 @@ prettier-plugin-solidity@^1.1.3:
semver "^7.3.8"
solidity-comments-extractor "^0.0.7"
-prettier@^2.0.0, prettier@^2.8.3:
+prettier@^2.0.0, prettier@^2.3.1, prettier@^2.8.3:
version "2.8.8"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da"
integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==
+prop-types@^15.7.2:
+ version "15.8.1"
+ resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
+ integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
+ dependencies:
+ loose-envify "^1.4.0"
+ object-assign "^4.1.1"
+ react-is "^16.13.1"
+
punycode@^2.1.0:
version "2.3.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
+randombytes@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
+ integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
+ dependencies:
+ safe-buffer "^5.1.0"
+
+react-is@^16.13.1, react-is@^16.7.0:
+ version "16.13.1"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
+ integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
+
+readable-stream@^3.6.0:
+ version "3.6.2"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
+ integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
+ dependencies:
+ inherits "^2.0.3"
+ string_decoder "^1.1.1"
+ util-deprecate "^1.0.1"
+
+reduce-flatten@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27"
+ integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==
+
+rehackt@0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/rehackt/-/rehackt-0.0.6.tgz#7a0a2247f2295e7548915417e44fbbf03bf004f4"
+ integrity sha512-l3WEzkt4ntlEc/IB3/mF6SRgNHA6zfQR7BlGOgBTOmx7IJJXojDASav+NsgXHFjHn+6RmwqsGPFgZpabWpeOdw==
+
require-from-string@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
@@ -388,6 +1374,21 @@ resolve-from@^4.0.0:
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
+response-iterator@^0.2.6:
+ version "0.2.6"
+ resolved "https://registry.yarnpkg.com/response-iterator/-/response-iterator-0.2.6.tgz#249005fb14d2e4eeb478a3f735a28fd8b4c9f3da"
+ integrity sha512-pVzEEzrsg23Sh053rmDUvLSkGXluZio0qu8VT6ukrYuvtjVfCbDZH9d6PGXb8HZfzdNZt8feXv/jvUzlhRgLnw==
+
+safe-buffer@^5.1.0, safe-buffer@~5.2.0:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
+ integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+
+scrypt-js@3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312"
+ integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==
+
semver@^7.3.8, semver@^7.5.2:
version "7.5.4"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
@@ -441,6 +1442,11 @@ solidity-comments-extractor@^0.0.7:
resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz#99d8f1361438f84019795d928b931f4e5c39ca19"
integrity sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==
+string-format@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b"
+ integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==
+
string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
@@ -450,6 +1456,13 @@ string-width@^4.2.3:
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
+string_decoder@^1.1.1:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
+ integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
+ dependencies:
+ safe-buffer "~5.2.0"
+
strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
@@ -457,6 +1470,13 @@ strip-ansi@^6.0.1:
dependencies:
ansi-regex "^5.0.1"
+strip-hex-prefix@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f"
+ integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==
+ dependencies:
+ is-hex-prefixed "1.0.0"
+
supports-color@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
@@ -471,6 +1491,21 @@ supports-color@^7.1.0:
dependencies:
has-flag "^4.0.0"
+symbol-observable@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-4.0.0.tgz#5b425f192279e87f2f9b937ac8540d1984b39205"
+ integrity sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==
+
+table-layout@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04"
+ integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==
+ dependencies:
+ array-back "^4.0.1"
+ deep-extend "~0.6.0"
+ typical "^5.2.0"
+ wordwrapjs "^4.0.0"
+
table@^6.8.1:
version "6.8.1"
resolved "https://registry.yarnpkg.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf"
@@ -487,6 +1522,79 @@ text-table@^0.2.0:
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
+tiny-invariant@^1.1.0:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127"
+ integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==
+
+tr46@~0.0.3:
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
+ integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
+
+treeify@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.1.0.tgz#4e31c6a463accd0943879f30667c4fdaff411bb8"
+ integrity sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==
+
+ts-command-line-args@^2.2.0:
+ version "2.5.1"
+ resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz#e64456b580d1d4f6d948824c274cf6fa5f45f7f0"
+ integrity sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==
+ dependencies:
+ chalk "^4.1.0"
+ command-line-args "^5.1.1"
+ command-line-usage "^6.1.0"
+ string-format "^2.0.0"
+
+ts-essentials@^7.0.1:
+ version "7.0.3"
+ resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38"
+ integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==
+
+ts-invariant@^0.10.3:
+ version "0.10.3"
+ resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.10.3.tgz#3e048ff96e91459ffca01304dbc7f61c1f642f6c"
+ integrity sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ==
+ dependencies:
+ tslib "^2.1.0"
+
+tslib@^2.1.0, tslib@^2.3.0:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
+ integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
+
+typechain@^8.3.2:
+ version "8.3.2"
+ resolved "https://registry.yarnpkg.com/typechain/-/typechain-8.3.2.tgz#1090dd8d9c57b6ef2aed3640a516bdbf01b00d73"
+ integrity sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==
+ dependencies:
+ "@types/prettier" "^2.1.1"
+ debug "^4.3.1"
+ fs-extra "^7.0.0"
+ glob "7.1.7"
+ js-sha3 "^0.8.0"
+ lodash "^4.17.15"
+ mkdirp "^1.0.4"
+ prettier "^2.3.1"
+ ts-command-line-args "^2.2.0"
+ ts-essentials "^7.0.1"
+
+typical@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4"
+ integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==
+
+typical@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066"
+ integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==
+
+universalify@^0.1.0:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
+ integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
+
uri-js@^4.2.2:
version "4.4.1"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
@@ -494,12 +1602,74 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
+utf8@3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1"
+ integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==
+
+util-deprecate@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+ integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
+
+web3-utils@^1.3.4:
+ version "1.10.4"
+ resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.4.tgz#0daee7d6841641655d8b3726baf33b08eda1cbec"
+ integrity sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A==
+ dependencies:
+ "@ethereumjs/util" "^8.1.0"
+ bn.js "^5.2.1"
+ ethereum-bloom-filters "^1.0.6"
+ ethereum-cryptography "^2.1.2"
+ ethjs-unit "0.1.6"
+ number-to-bn "1.7.0"
+ randombytes "^2.1.0"
+ utf8 "3.0.0"
+
+webidl-conversions@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
+ integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
+
+whatwg-url@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
+ integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
+ dependencies:
+ tr46 "~0.0.3"
+ webidl-conversions "^3.0.0"
+
+wordwrapjs@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f"
+ integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==
+ dependencies:
+ reduce-flatten "^2.0.0"
+ typical "^5.2.0"
+
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
+ws@7.4.6:
+ version "7.4.6"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"
+ integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==
+
yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
+
+zen-observable-ts@^1.2.5:
+ version "1.2.5"
+ resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-1.2.5.tgz#6c6d9ea3d3a842812c6e9519209365a122ba8b58"
+ integrity sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg==
+ dependencies:
+ zen-observable "0.8.15"
+
+zen-observable@0.8.15:
+ version "0.8.15"
+ resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15"
+ integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==