This commit is contained in:
armaniferrante 2021-10-12 12:34:05 -07:00
parent e4f63f7c8a
commit ca3aca3ce3
No known key found for this signature in database
GPG Key ID: 58BEF301E91F7828
6 changed files with 227 additions and 148 deletions

58
Cargo.lock generated
View File

@ -25,9 +25,7 @@ checksum = "6b2d54853319fd101b8dd81de382bcbf3e03410a64d8928bbee85a3e7dcde483"
[[package]]
name = "anchor-attribute-access-control"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4ff7b54a5d232ce177fb5e1d42bb767678e5df0434b205a045afa8fc7a83a23"
version = "0.17.0"
dependencies = [
"anchor-syn",
"anyhow",
@ -39,9 +37,7 @@ dependencies = [
[[package]]
name = "anchor-attribute-account"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f2c53504cae7e67cd4d7a2d6db6828293923c0a0d80e8ae29e67bf517548d6e"
version = "0.17.0"
dependencies = [
"anchor-syn",
"anyhow",
@ -54,9 +50,7 @@ dependencies = [
[[package]]
name = "anchor-attribute-error"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8341b2661f13ca6e4dfb55e21f49908774d9fb915c56dbd7b804668c3eb53380"
version = "0.17.0"
dependencies = [
"anchor-syn",
"proc-macro2",
@ -66,9 +60,7 @@ dependencies = [
[[package]]
name = "anchor-attribute-event"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e5e4e868c019d872baa669b43796a877e6a66da4a286a1b8467ba747428804d"
version = "0.17.0"
dependencies = [
"anchor-syn",
"anyhow",
@ -79,9 +71,7 @@ dependencies = [
[[package]]
name = "anchor-attribute-interface"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db9d1de704bf2845d9edc7fe368a48943b672f2e770251c4d929d6712bac367d"
version = "0.17.0"
dependencies = [
"anchor-syn",
"anyhow",
@ -93,9 +83,7 @@ dependencies = [
[[package]]
name = "anchor-attribute-program"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f035ee71ffa1db5f06694a650aa61ba4265f9fa1263fed3b744b2cd8a31f448a"
version = "0.17.0"
dependencies = [
"anchor-syn",
"anyhow",
@ -106,9 +94,7 @@ dependencies = [
[[package]]
name = "anchor-attribute-state"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1a2bfe33f0fc0aeffe01dda3aa36417eb96ebcfc39dfdb003ef968d5ed9a70f"
version = "0.17.0"
dependencies = [
"anchor-syn",
"anyhow",
@ -119,9 +105,7 @@ dependencies = [
[[package]]
name = "anchor-derive-accounts"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fffb0562db113cd2491e825e0f4df8d050dc14371dec7cccf757efcf86445451"
version = "0.17.0"
dependencies = [
"anchor-syn",
"anyhow",
@ -132,9 +116,7 @@ dependencies = [
[[package]]
name = "anchor-lang"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bd220aca840a0067d43da61e802a5e4ac13582f0baef7aa33c79d42a0110086"
version = "0.17.0"
dependencies = [
"anchor-attribute-access-control",
"anchor-attribute-account",
@ -153,22 +135,19 @@ dependencies = [
[[package]]
name = "anchor-spl"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f34afdc6678b3c2563403f6ca2a6d59b2407cd3334757e2761c4776e0339764"
version = "0.17.0"
dependencies = [
"anchor-lang",
"lazy_static",
"serum_dex",
"solana-program",
"spl-associated-token-account",
"spl-token",
]
[[package]]
name = "anchor-syn"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93cade4d95b7edd8d6be4e8243b935e26dee6eb1a50bd226392cefd0a31e682c"
version = "0.17.0"
dependencies = [
"anyhow",
"bs58 0.3.1",
@ -991,8 +970,7 @@ dependencies = [
[[package]]
name = "serum_dex"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02705854bae4622e552346c8edd43ab90c7425da35d63d2c689f39238f8d8b25"
source = "git+https://github.com/project-serum/serum-dex?rev=1be91f2#1be91f2863d8ecede32daaae7e768034e24bbc79"
dependencies = [
"arrayref",
"bincode",
@ -1128,6 +1106,16 @@ dependencies = [
"syn",
]
[[package]]
name = "spl-associated-token-account"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "393e2240d521c3dd770806bff25c2c00d761ac962be106e14e22dd912007f428"
dependencies = [
"solana-program",
"spl-token",
]
[[package]]
name = "spl-token"
version = "3.2.0"

View File

@ -1,12 +1,13 @@
{
"dependencies": {
"@project-serum/anchor": "^0.16.1"
"@project-serum/anchor": "^0.17.1-beta.1",
"@solana/spl-token": "^0.1.8"
},
"devDependencies": {
"@types/mocha": "^9.0.0",
"chai": "^4.3.4",
"mocha": "^9.0.3",
"ts-mocha": "^8.0.0",
"@types/mocha": "^9.0.0",
"typescript": "^4.3.5"
}
}

View File

@ -15,5 +15,6 @@ cpi = ["no-entrypoint"]
default = []
[dependencies]
anchor-lang = "0.16.1"
anchor-spl = "0.16.1"
# TODO: use versions after next Anchor publish.
anchor-lang = { git = "https://github.com/project-serum/anchor" }
anchor-spl = { git = "https://github.com/project-serum/anchor" }

View File

@ -1,5 +1,8 @@
use anchor_lang::__private::bytemuck::Zeroable;
use anchor_lang::prelude::*;
use anchor_spl::associated_token::AssociatedToken;
use anchor_spl::token::{self, Mint, Token, TokenAccount};
use std::mem::size_of;
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
@ -7,63 +10,94 @@ declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
pub mod governance_registry {
use super::*;
/// Creates a new voting registrar.
/// Creates a new voting registrar. There can only be a single regsitrar
/// per governance realm.
pub fn init_registrar(
ctx: Context<InitRegistrar>,
_voting_mint_decimals: u8,
registrar_bump: u8,
voting_mint_bump: u8,
_voting_mint_decimals: u8,
) -> Result<()> {
let registrar = &mut ctx.accounts.registrar;
let registrar = &mut ctx.accounts.registrar.load_init()?;
registrar.registrar_bump = registrar_bump;
registrar.voting_mint_bump = voting_mint_bump;
registrar.realm = ctx.accounts.realm.key();
registrar.voting_mint = ctx.accounts.voting_mint.key();
registrar.authority = ctx.accounts.authority.key();
if true {
panic!("HELLO WORLD");
}
Ok(())
}
/// Creates a new voter account.
/// Creates a new voter account. There can only be a single voter per
/// user wallet.
pub fn init_voter(ctx: Context<InitVoter>, voter_bump: u8) -> Result<()> {
let voter = &mut ctx.accounts.voter;
let voter = &mut ctx.accounts.voter.load_mut()?;
voter.voter_bump = voter_bump;
voter.authority = ctx.accounts.authority.key();
voter.registrar = ctx.accounts.registrar.key();
voter.rights_outstanding = 0;
Ok(())
}
/// Creates a new exchange rate for a given mint. The exchange rate
/// allows one to deposit one token into the registrar and receive voting
/// tokens in response. Only the registrar authority can invoke this.
pub fn add_exchange_rate(
ctx: Context<AddExchangeRate>,
rate: u64,
rate_bump: u8,
vault_bump: u8,
) -> Result<()> {
require!(rate > 0, InvalidRate);
let rate = &mut ctx.accounts.exchange_rate;
rate.deposit_mint = ctx.accounts.deposit_mint.key();
rate.rate_bump = rate_bump;
rate.vault_bump = vault_bump;
/// Creates a new exchange rate for a given mint. This allows a voter to
/// deposit the mint in exchange for vTokens. There can only be a single
/// exchange rate per mint.
pub fn add_exchange_rate(ctx: Context<AddExchangeRate>, er: ExchangeRateEntry) -> Result<()> {
require!(er.rate > 0, InvalidRate);
let registrar = &mut ctx.accounts.registrar.load_mut()?;
let idx = registrar
.rates
.iter()
.position(|r| !r.is_used)
.ok_or(ErrorCode::RatesFull)?;
registrar.rates[idx] = er;
Ok(())
}
/// Deposits tokens into the registrar in exchange for voting rights that
/// can be used with a DAO.
pub fn mint_voting_rights(ctx: Context<MintVotingRights>, amount: u64) -> Result<()> {
// Deposit tokens into the registrar.
token::transfer((&*ctx.accounts).into(), amount)?;
/// Deposits tokens into the registrar in exchange for *frozen* voting
/// tokens. These tokens are not used for anything other than displaying
/// the amount in walletes.
pub fn deposit(ctx: Context<Deposit>, amount: u64) -> Result<()> {
let registrar = &mut ctx.accounts.registrar.load()?;
let voter = &mut ctx.accounts.voter.load_mut()?;
// Get the exchange rate entry associated with this deposit.
let er_idx = registrar
.rates
.iter()
.position(|r| r.mint == ctx.accounts.deposit_mint.key())
.ok_or(ErrorCode::ExchangeRateEntryNotFound)?;
let er_entry = registrar.rates[er_idx];
// Get the deposit entry associated with this deposit.
let deposit_entry = {
match voter.deposits.iter().position(|deposit_entry| {
registrar.rates[deposit_entry.rate_idx as usize].mint
== ctx.accounts.deposit_mint.key()
}) {
// Lazily instantiate the deposit if needed.
None => {
let free_entry_idx = voter
.deposits
.iter()
.position(|deposit_entry| !deposit_entry.is_used)
.ok_or(ErrorCode::DepositEntryFull)?;
let entry = &mut voter.deposits[free_entry_idx];
entry.is_used = true;
entry.rate_idx = free_entry_idx as u8;
entry
}
// Use the existing deposit.
Some(e) => &mut voter.deposits[e],
}
};
deposit_entry.amount += amount;
// Calculate the amount of voting tokens to mint.
let scaled_amount = { amount };
let scaled_amount = er_entry.rate * amount;
// Deposit tokens into the registrar.
token::transfer((&*ctx.accounts).into(), amount)?;
// Mint vote tokens to the depositor.
token::mint_to((&*ctx.accounts).into(), scaled_amount)?;
@ -71,8 +105,16 @@ pub mod governance_registry {
Ok(())
}
/// Updates the Voter's voting rights by decaying locked deposits.
pub fn decay_voting_rights(ctx: Context<DecayVotingRights>) -> Result<()> {
/// Withdraws tokens from a deposit entry, if they are unlocked according
/// to a vesting schedule.
pub fn withdraw(ctx: Context<Withdraw>, amount: u64) -> Result<()> {
// todo
Ok(())
}
/// Updates a vesting schedule. Can only increase the lockup time. If all
/// tokens are unlocked, then the period count can also be updated.
pub fn update_schedule(ctx: Context<UpdateSchedule>) -> Result<()> {
// todo
Ok(())
}
@ -81,15 +123,16 @@ pub mod governance_registry {
// Contexts.
#[derive(Accounts)]
#[instruction(voting_mint_decimals: u8, registrar_bump: u8, voting_mint_bump: u8)]
#[instruction(registrar_bump: u8, voting_mint_bump: u8, voting_mint_decimals: u8)]
pub struct InitRegistrar<'info> {
#[account(
init,
seeds = [realm.key().as_ref()],
bump = registrar_bump,
payer = payer,
space = 8 + size_of::<Registrar>()
)]
registrar: Account<'info, Registrar>,
registrar: AccountLoader<'info, Registrar>,
#[account(
init,
seeds = [registrar.key().as_ref()],
@ -115,52 +158,42 @@ pub struct InitVoter<'info> {
seeds = [registrar.key().as_ref(), authority.key().as_ref()],
bump = voter_bump,
payer = authority,
space = 8 + size_of::<Voter>()
)]
voter: Account<'info, Voter>,
registrar: Account<'info, Registrar>,
voter: AccountLoader<'info, Voter>,
registrar: AccountLoader<'info, Registrar>,
authority: Signer<'info>,
system_program: Program<'info, System>,
}
#[derive(Accounts)]
#[instruction(rate_bump: u8, vault_bump: u8)]
#[instruction(rate: ExchangeRateEntry)]
pub struct AddExchangeRate<'info> {
#[account(
init,
seeds = [b"exchange-rate", registrar.key().as_ref(), deposit_mint.key().as_ref()],
bump = rate_bump,
payer = payer,
)]
exchange_rate: Account<'info, ExchangeRate>,
#[account(
init,
seeds = [b"exchange-vault", exchange_rate.key().as_ref()],
bump = vault_bump,
payer = payer,
token::authority = registrar,
token::mint = deposit_mint,
associated_token::authority = registrar,
associated_token::mint = deposit_mint,
)]
exchange_vault: Account<'info, TokenAccount>,
deposit_mint: Account<'info, Mint>,
#[account(has_one = authority)]
registrar: Account<'info, Registrar>,
registrar: AccountLoader<'info, Registrar>,
authority: Signer<'info>,
payer: Signer<'info>,
rent: Sysvar<'info, Rent>,
token_program: Program<'info, Token>,
associated_token_program: Program<'info, AssociatedToken>,
system_program: Program<'info, System>,
}
#[derive(Accounts)]
pub struct MintVotingRights<'info> {
pub struct Deposit<'info> {
#[account(has_one = authority)]
voter: AccountLoader<'info, Voter>,
#[account(
seeds = [b"exchange-rate", registrar.key().as_ref(), deposit_mint.key().as_ref()],
bump = exchange_rate.rate_bump,
)]
exchange_rate: Account<'info, ExchangeRate>,
#[account(
seeds = [b"exchange-vault", exchange_rate.key().as_ref()],
bump = exchange_rate.vault_bump,
associated_token::authority = registrar,
associated_token::mint = deposit_mint,
)]
exchange_vault: Account<'info, TokenAccount>,
#[account(
@ -168,71 +201,83 @@ pub struct MintVotingRights<'info> {
)]
deposit_token: Account<'info, TokenAccount>,
#[account(
constraint = registrar.voting_mint == voting_token.mint,
constraint = registrar.load()?.voting_mint == voting_token.mint,
)]
voting_token: Account<'info, TokenAccount>,
authority: Signer<'info>,
registrar: Account<'info, Registrar>,
registrar: AccountLoader<'info, Registrar>,
deposit_mint: Account<'info, Mint>,
voting_mint: Account<'info, Mint>,
token_program: Program<'info, Token>,
}
#[derive(Accounts)]
pub struct DecayVotingRights<'info> {
voter: Account<'info, Voter>,
deposit: Account<'info, VoterDeposit>,
pub struct Withdraw {
// todo
}
#[derive(Accounts)]
pub struct UpdateSchedule {
// todo
}
// Accounts.
/// Instance of a voting rights distributor.
#[account]
#[derive(Default)]
#[account(zero_copy)]
pub struct Registrar {
pub authority: Pubkey,
pub realm: Pubkey,
pub voting_mint: Pubkey,
pub voting_mint_bump: u8,
pub registrar_bump: u8,
pub rates: [ExchangeRateEntry; 32],
}
/// User account for minting voting rights.
#[account]
#[derive(Default)]
#[account(zero_copy)]
pub struct Voter {
pub authority: Pubkey,
pub registrar: Pubkey,
pub rights_outstanding: u64,
pub voter_bump: u8,
}
pub struct Deposit {
pub mint_idx: u8,
pub lockup_years: u8,
pub amount: u64,
}
/// Sub account for a
#[account]
pub struct VoterDeposit {
amount: u64,
exchange_rate: Pubkey,
pub deposits: [DepositEntry; 32],
}
/// Exchange rate for an asset that can be used to mint voting rights.
#[account]
#[derive(Default)]
pub struct ExchangeRate {
deposit_mint: Pubkey,
rate: u64,
rate_bump: u8,
vault_bump: u8,
#[zero_copy]
#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct ExchangeRateEntry {
// True if the exchange rate entry is being used.
pub is_used: bool,
pub mint: Pubkey,
pub rate: u64,
}
unsafe impl Zeroable for ExchangeRateEntry {}
#[zero_copy]
pub struct DepositEntry {
// True if the deposit entry is being used.
pub is_used: bool,
// Points to the ExchangeRate this deposit uses.
pub rate_idx: u8,
pub amount: u64,
// Locked state.
period_count: u64,
start_ts: i64,
end_ts: i64,
pub period_count: u64,
pub start_ts: i64,
pub end_ts: i64,
}
impl DepositEntry {
/// Returns the voting power given by this deposit, scaled to account for
/// a lockup.
pub fn voting_power(&self) -> u64 {
let locked_multiplier = 1; // todo
self.amount * locked_multiplier
}
}
// Error.
@ -241,14 +286,19 @@ pub struct ExchangeRate {
pub enum ErrorCode {
#[msg("Exchange rate must be greater than zero")]
InvalidRate,
#[msg("")]
RatesFull,
#[msg("")]
ExchangeRateEntryNotFound,
#[msg("")]
DepositEntryNotFound,
DepositEntryFull,
}
// CpiContext.
impl<'info> From<&MintVotingRights<'info>>
for CpiContext<'_, '_, '_, 'info, token::Transfer<'info>>
{
fn from(accs: &MintVotingRights<'info>) -> Self {
impl<'info> From<&Deposit<'info>> for CpiContext<'_, '_, '_, 'info, token::Transfer<'info>> {
fn from(accs: &Deposit<'info>) -> Self {
let program = accs.token_program.to_account_info();
let accounts = token::Transfer {
from: accs.deposit_token.to_account_info(),
@ -259,8 +309,8 @@ impl<'info> From<&MintVotingRights<'info>>
}
}
impl<'info> From<&MintVotingRights<'info>> for CpiContext<'_, '_, '_, 'info, token::MintTo<'info>> {
fn from(accs: &MintVotingRights<'info>) -> Self {
impl<'info> From<&Deposit<'info>> for CpiContext<'_, '_, '_, 'info, token::MintTo<'info>> {
fn from(accs: &Deposit<'info>) -> Self {
let program = accs.token_program.to_account_info();
let accounts = token::MintTo {
mint: accs.voting_mint.to_account_info(),

View File

@ -1,17 +1,19 @@
import * as anchor from '@project-serum/anchor';
import { Program } from '@project-serum/anchor';
import { PublicKey, Keypair, SystemProgram, SYSVAR_RENT_PUBKEY } from '@solana/web3.js';
import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
import { GovernanceRegistry } from '../target/types/governance_registry';
describe('voting-rights', () => {
// Configure the client to use the local cluster.
anchor.setProvider(anchor.Provider.env());
const program = anchor.workspace.GovernanceRegistry;
const realm = Keypair.generate().publicKey;
const program = anchor.workspace.GovernanceRegistry as Program<GovernanceRegistry>;
// Initialized variables shared across tests.
const realm = Keypair.generate().publicKey;
const votingMintDecimals = 6;
// Uninitialized variables shared across tests.
let registrar: PublicKey, votingMint: PublicKey, voter: PublicKey;
let registrarBump: number, votingMintBump: number, voterBump: number;
@ -39,7 +41,7 @@ describe('voting-rights', () => {
});
it('Initializes a registrar', async () => {
await program.rpc.initRegistrar(votingMintDecimals, registrarBump, votingMintBump, {
await program.rpc.initRegistrar(registrarBump, votingMintBump, votingMintDecimals, {
accounts: {
registrar,
votingMint,

View File

@ -2,17 +2,17 @@
# yarn lockfile v1
"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5":
"@babel/runtime@^7.10.5", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5":
version "7.15.4"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a"
integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==
dependencies:
regenerator-runtime "^0.13.4"
"@project-serum/anchor@^0.16.1":
version "0.16.1"
resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.16.1.tgz#e044280e4534a966161a101619f5259252eda8ff"
integrity sha512-nbpxo5xgENkdDqfRBMMhCqicj9Mc3QcGFOy1cl5j7uYqvFjdOfkOMcP19sf6/m4wmgaclfiYfWeHALy7XDOubQ==
"@project-serum/anchor@^0.17.1-beta.1":
version "0.17.1-beta.1"
resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.17.1-beta.1.tgz#0532b4534c6a86e67e8530040c717979240f1dbe"
integrity sha512-W23rI48nNm6sM+3L6jUh4kSWh5cLJWwJHiohB2AnnG+9jYs/NSgCcope8dP0g2DeHITCo5E/VpZpZc4Fulqqpg==
dependencies:
"@project-serum/borsh" "^0.2.2"
"@solana/web3.js" "^1.17.0"
@ -44,6 +44,18 @@
dependencies:
buffer "~6.0.3"
"@solana/spl-token@^0.1.8":
version "0.1.8"
resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.1.8.tgz#f06e746341ef8d04165e21fc7f555492a2a0faa6"
integrity sha512-LZmYCKcPQDtJgecvWOgT/cnoIQPWjdH+QVyzPcFvyDUiT0DiRjZaam4aqNUyvchLFhzgunv3d9xOoyE34ofdoQ==
dependencies:
"@babel/runtime" "^7.10.5"
"@solana/web3.js" "^1.21.0"
bn.js "^5.1.0"
buffer "6.0.3"
buffer-layout "^1.2.0"
dotenv "10.0.0"
"@solana/web3.js@^1.17.0":
version "1.29.0"
resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.29.0.tgz#61cb40e2190f13ae8084d20012cb81f8fade78fa"
@ -64,6 +76,26 @@
superstruct "^0.14.2"
tweetnacl "^1.0.0"
"@solana/web3.js@^1.21.0":
version "1.29.2"
resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.29.2.tgz#05c162f477c226ee3211f8ee8c1c6d4203e08f54"
integrity sha512-gtoHzimv7upsKF2DIO4/vNfIMKN+cxSImBHvsdiMyp9IPqb8sctsHVU/+80xXl0JKXVKeairDv5RvVnesJYrtw==
dependencies:
"@babel/runtime" "^7.12.5"
"@solana/buffer-layout" "^3.0.0"
bn.js "^5.0.0"
borsh "^0.4.0"
bs58 "^4.0.1"
buffer "6.0.1"
cross-fetch "^3.1.4"
crypto-hash "^1.2.2"
jayson "^3.4.4"
js-sha3 "^0.8.0"
rpc-websockets "^7.4.2"
secp256k1 "^4.0.2"
superstruct "^0.14.2"
tweetnacl "^1.0.0"
"@types/bn.js@^4.11.5":
version "4.11.6"
resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c"
@ -214,7 +246,7 @@ bn.js@^4.11.9:
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88"
integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==
bn.js@^5.0.0, bn.js@^5.1.2:
bn.js@^5.0.0, bn.js@^5.1.0, bn.js@^5.1.2:
version "5.2.0"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002"
integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==
@ -279,7 +311,7 @@ buffer@6.0.1:
base64-js "^1.3.1"
ieee754 "^1.2.1"
buffer@~6.0.3:
buffer@6.0.3, 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==
@ -434,6 +466,11 @@ dot-case@^3.0.4:
no-case "^3.0.4"
tslib "^2.0.3"
dotenv@10.0.0:
version "10.0.0"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81"
integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==
elliptic@^6.5.2:
version "6.5.4"
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"