Skip to content

Commit

Permalink
feat: contract operator (#68)
Browse files Browse the repository at this point in the history
* operator

* set operator command

* operator set

* refactor: operator -> manager (#69)

* rename owner to admin

* rename to manager

* revert: owner -> admin

* fix: method names

Co-authored-by: Linguists <95207870+linguists@users.noreply.github.com>

* style: code format

* refactor: manager commands

Co-authored-by: Linguists <95207870+linguists@users.noreply.github.com>
  • Loading branch information
dongcool and linguists authored Mar 22, 2022
1 parent c58743a commit fdbacc6
Show file tree
Hide file tree
Showing 12 changed files with 635 additions and 409 deletions.
42 changes: 42 additions & 0 deletions bin/commands/add-manager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const { init } = require("../near");

exports.command = 'add-manager <address>';
exports.desc = 'Add manager';
exports.builder = yargs => {
yargs
.positional('address', {
describe: 'Contract address',
type: 'string'
})
.option('network', {
describe: 'network ID',
default: 'testnet',
choices: ['testnet', 'mainnet']
})
.option('signer', {
describe: 'signer account Id to call contract'
})
.option('manager', {
describe: 'new manager ID'
})
.demandOption(['signer', 'manager'])
}

exports.handler = async function (argv) {
const { address, manager } = argv;

const near = await init(argv.network);
const signer = await near.account(argv.signer);

console.log(`Adding manager ${manager}`);

await signer.functionCall({
contractId: address,
methodName: 'add_manager',
args: {
new_manager_id: manager
}
});

console.log('done');
}
42 changes: 42 additions & 0 deletions bin/commands/del-manager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const { init } = require("../near");

exports.command = 'del-manager <address>';
exports.desc = 'Remove manager';
exports.builder = yargs => {
yargs
.positional('address', {
describe: 'Contract address',
type: 'string'
})
.option('network', {
describe: 'network ID',
default: 'testnet',
choices: ['testnet', 'mainnet']
})
.option('signer', {
describe: 'signer account Id to call contract'
})
.option('manager', {
describe: 'manager ID to remove'
})
.demandOption(['signer', 'manager'])
}

exports.handler = async function (argv) {
const { address, manager } = argv;

const near = await init(argv.network);
const signer = await near.account(argv.signer);

console.log(`Removing manager ${manager}`);

await signer.functionCall({
contractId: address,
methodName: 'remove_manager',
args: {
manager_id: manager
}
});

console.log('done');
}
27 changes: 27 additions & 0 deletions bin/commands/list-managers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const { init } = require("../near");

exports.command = 'list-managers <address>';
exports.desc = 'List manager';
exports.builder = yargs => {
yargs
.positional('address', {
describe: 'Contract address',
type: 'string'
})
.option('network', {
describe: 'network ID',
default: 'testnet',
choices: ['testnet', 'mainnet']
})
}

exports.handler = async function (argv) {
const { address } = argv;

const near = await init(argv.network);
const contract = await near.account(address);

const managers = await contract.viewFunction(address, 'get_managers');

console.log(managers);
}
3 changes: 3 additions & 0 deletions contracts/linear/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ pub const ERR_NO_ENOUGH_INIT_DEPOSIT: &str =
// owner
pub const ERR_NOT_OWNER: &str = "Only owner can perform this action";

// manager
pub const ERR_NOT_MANAGER: &str = "Only manager can perform this action";

// account
pub const ERR_NO_ACCOUNT: &str = "Account not found";
pub const ERR_UNREGISTER_POSITIVE_UNSTAKED: &str = "Cannot delete the account because the unstaked amount is not empty. Withdraw your balance first.";
Expand Down
24 changes: 23 additions & 1 deletion contracts/linear/src/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ impl LiquidStakingContract {
}

/// When there are rewards, a part of them will be
/// given to operator/treasury by minting new LiNEAR tokens.
/// given to executor, manager or treasury by minting new LiNEAR tokens.
pub(crate) fn internal_distribute_staking_rewards(&mut self, rewards: Balance) {
let hashmap: HashMap<AccountId, Fraction> = self.internal_get_beneficiaries();
for (account_id, fraction) in hashmap.iter() {
Expand Down Expand Up @@ -313,3 +313,25 @@ impl LiquidStakingContract {
}
}
}

// -- manager related methods
impl LiquidStakingContract {
pub(crate) fn internal_add_manager(&mut self, manager_id: &AccountId) {
self.managers.insert(manager_id);
}

pub(crate) fn internal_remove_manager(&mut self, manager_id: &AccountId) -> bool {
self.managers.remove(manager_id)
}

pub(crate) fn internal_get_managers(&self) -> Vec<AccountId> {
self.managers.to_vec()
}

pub(crate) fn assert_manager(&self) {
require!(
self.managers.contains(&env::predecessor_account_id()),
ERR_NOT_MANAGER
);
}
}
7 changes: 6 additions & 1 deletion contracts/linear/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,16 @@ pub(crate) enum StorageKey {
Farms,
// AuthorizedUsers,
AuthorizedFarmTokens,
Managers,
}

#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)]
pub struct LiquidStakingContract {
/// The account ID of the owner who's running the liquid staking contract.
/// The account ID of the owner
owner_id: AccountId,
/// The accounts that are able to change key parameters and settings in the contract such as validator pool membership
managers: UnorderedSet<AccountId>,
/// The account ID of the treasury that manages portion of the received fees and rewards.
treasury_id: AccountId,
/// Total amount of LiNEAR that was minted (minus burned).
Expand Down Expand Up @@ -134,6 +137,7 @@ impl LiquidStakingContract {
);
let mut this = Self {
owner_id: owner_id.clone(),
managers: UnorderedSet::new(StorageKey::Managers),
treasury_id: owner_id.clone(),
total_share_amount: 10 * ONE_NEAR,
total_staked_near_amount: 10 * ONE_NEAR,
Expand All @@ -155,6 +159,7 @@ impl LiquidStakingContract {
// authorized_users: UnorderedSet::new(StorageKey::AuthorizedUsers),
authorized_farm_tokens: UnorderedSet::new(StorageKey::AuthorizedFarmTokens),
};
this.internal_add_manager(&owner_id);
this.measure_account_storage_usage();
this
}
Expand Down
10 changes: 10 additions & 0 deletions contracts/linear/src/owner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ impl LiquidStakingContract {
self.owner_id = new_owner_id;
}

pub fn add_manager(&mut self, new_manager_id: AccountId) {
self.assert_owner();
self.internal_add_manager(&new_manager_id);
}

pub fn remove_manager(&mut self, manager_id: AccountId) -> bool {
self.assert_owner();
self.internal_remove_manager(&manager_id)
}

pub fn set_beneficiary(&mut self, account_id: AccountId, fraction: Fraction) {
self.assert_owner();
fraction.assert_valid();
Expand Down
10 changes: 4 additions & 6 deletions contracts/linear/src/validator_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ fn min3(x: u128, y: u128, z: u128) -> u128 {
#[near_bindgen]
impl LiquidStakingContract {
pub fn add_validator(&mut self, validator_id: AccountId, weight: u16) -> Validator {
self.assert_owner();
self.assert_manager();
self.validator_pool.add_validator(&validator_id, weight)
}

Expand All @@ -218,7 +218,7 @@ impl LiquidStakingContract {
validator_ids: Vec<AccountId>,
weights: Vec<u16>,
) -> Vec<Validator> {
self.assert_owner();
self.assert_manager();
require!(validator_ids.len() == weights.len(), ERR_BAD_VALIDATOR_LIST);
let mut results: Vec<Validator> = vec![];
for i in 0..validator_ids.len() {
Expand All @@ -232,12 +232,12 @@ impl LiquidStakingContract {
}

pub fn remove_validator(&mut self, validator_id: AccountId) -> Validator {
self.assert_owner();
self.assert_manager();
self.validator_pool.remove_validator(&validator_id)
}

pub fn update_weight(&mut self, validator_id: AccountId, weight: u16) {
self.assert_owner();
self.assert_manager();
self.validator_pool.update_weight(&validator_id, weight);
}

Expand All @@ -247,15 +247,13 @@ impl LiquidStakingContract {
}

pub fn get_validator(&self, validator_id: AccountId) -> ValidatorInfo {
self.assert_owner();
self.validator_pool
.get_validator(&validator_id)
.expect(ERR_VALIDATOR_NOT_EXIST)
.get_info()
}

pub fn get_validators(&self, offset: u64, limit: u64) -> Vec<ValidatorInfo> {
self.assert_owner();
self.validator_pool
.get_validators(offset, limit)
.iter()
Expand Down
4 changes: 4 additions & 0 deletions contracts/linear/src/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ impl LiquidStakingContract {
self.internal_get_beneficiaries()
}

pub fn get_managers(&self) -> Vec<AccountId> {
self.internal_get_managers()
}

pub fn get_summary(&self) -> Summary {
Summary {
total_share_amount: self.total_share_amount.into(),
Expand Down
Loading

0 comments on commit fdbacc6

Please sign in to comment.