Skip to content

Commit

Permalink
refactor: integrate contract governance into treasury
Browse files Browse the repository at this point in the history
extract some common setup code in tests.
  • Loading branch information
Chris-Hibbert committed Jul 7, 2021
1 parent abed906 commit a9ad9ab
Show file tree
Hide file tree
Showing 8 changed files with 303 additions and 417 deletions.
5 changes: 4 additions & 1 deletion packages/governance/src/contractGovernor.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,10 @@ const start = zcf => {
paramSet,
);
assert(governed, X`All governed parameters must be mentioned in terms`);
governedContracts.init(governedInstance, []);
// a contract can have more than a single set of governed params.
if (!governedContracts.has(governedInstance)) {
governedContracts.init(governedInstance, []);
}

return Far('contract governor', {
/** @type {CreateQuestion} */
Expand Down
1 change: 1 addition & 0 deletions packages/treasury/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"@agoric/nat": "^4.1.0",
"@agoric/notifier": "^0.3.22",
"@agoric/promise-kit": "^0.2.20",
"@agoric/same-structure": "^0.1.20",
"@agoric/store": "^0.4.22",
"@agoric/swingset-vat": "^0.18.6",
"@agoric/zoe": "^0.17.5"
Expand Down
21 changes: 9 additions & 12 deletions packages/treasury/src/params.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,20 @@ export const LIQUIDATION_MARGIN_KEY = 'LiquidationMargin';
export const INTEREST_RATE_KEY = 'InterestRate';
export const LOAN_FEE_KEY = 'LoanFee';

export const governedParameterTerms = () => ({
loanParams: {
POOL_FEE_KEY,
PROTOCOL_FEE_KEY,
},
poolParams: {
export const governedParameterTerms = {
loanParams: [POOL_FEE_KEY, PROTOCOL_FEE_KEY],
poolParams: [
CHARGING_PERIOD_KEY,
RECORDING_PERIOD_KEY,
INITIAL_MARGIN_KEY,
LIQUIDATION_MARGIN_KEY,
INTEREST_RATE_KEY,
LOAN_FEE_KEY,
},
});
],
};

export const makeFeeGovernor = loanParams => {
/** @type {FeeGovernor} */
export const makeFeeParamManager = loanParams => {
/** @type {FeeParamManager} */
return buildParamManager([
{
name: POOL_FEE_KEY,
Expand All @@ -44,8 +41,8 @@ export const makeFeeGovernor = loanParams => {
]);
};

export const makePoolGovernor = (loanParams, rates) => {
/** @type {PoolGovernor} */
export const makePoolParamManager = (loanParams, rates) => {
/** @type {PoolParamManager} */
return buildParamManager([
{
name: CHARGING_PERIOD_KEY,
Expand Down
45 changes: 31 additions & 14 deletions packages/treasury/src/stablecoinMachine.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import '@agoric/governance/src/exported';
// can't redeem them outright, that would drain the utility from the economy.

import { E } from '@agoric/eventual-send';
import { assert, details, q } from '@agoric/assert';
import { assert, q, details as X } from '@agoric/assert';
import makeStore from '@agoric/store';
import {
assertProposalShape,
Expand All @@ -33,16 +33,18 @@ import {
makeRatioFromAmounts,
} from '@agoric/zoe/src/contractSupport/ratio';
import { AmountMath } from '@agoric/ertp';
import { sameStructure } from '@agoric/same-structure';

import { makeTracer } from './makeTracer';
import { makeVaultManager } from './vaultManager';
import { makeLiquidationStrategy } from './liquidateMinimum';
import { makeMakeCollectFeesInvitation } from './collectRewardFees';
import {
makePoolGovernor,
makeFeeGovernor,
makePoolParamManager,
makeFeeParamManager,
PROTOCOL_FEE_KEY,
POOL_FEE_KEY,
governedParameterTerms as governedParameterLocal,
} from './params';

const trace = makeTracer('ST');
Expand All @@ -57,22 +59,32 @@ export async function start(zcf) {
timerService,
liquidationInstall,
bootstrapPaymentValue = 0n,
electionManager,
governedParams,
} = zcf.getTerms();

assert.typeof(
loanParams.chargingPeriod,
'bigint',
details`chargingPeriod (${q(loanParams.chargingPeriod)}) must be a BigInt`,
X`chargingPeriod (${q(loanParams.chargingPeriod)}) must be a BigInt`,
);
assert.typeof(
loanParams.recordingPeriod,
'bigint',
details`recordingPeriod (${q(
loanParams.recordingPeriod,
)}) must be a BigInt`,
X`recordingPeriod (${q(loanParams.recordingPeriod)}) must be a BigInt`,
);

const feeGovernor = makeFeeGovernor(loanParams);
assert(
sameStructure(governedParams, harden(governedParameterLocal)),
X`Terms must match ${governedParameterLocal}`,
);
const governorPublic = E(zcf.getZoeService()).getPublicFacet(electionManager);
const feeParams = makeFeeParamManager(loanParams);
const feeGovernor = await E(governorPublic).governContract(
zcf.getInstance(),
feeParams,
'loanParams',
);

const [runMint, govMint] = await Promise.all([
zcf.makeZCFMint('RUN', undefined, harden({ decimalPlaces: 6 })),
Expand Down Expand Up @@ -126,8 +138,8 @@ export async function start(zcf) {
timer: timerService,
// TODO(hibbert): make the AMM use a paramManager. For now, the values
// are fixed after creation of an autoswap instance.
poolFee: feeGovernor.getParams()[POOL_FEE_KEY].value,
protocolFee: feeGovernor.getParams()[PROTOCOL_FEE_KEY].value,
poolFee: feeParams.getParams()[POOL_FEE_KEY].value,
protocolFee: feeParams.getParams()[PROTOCOL_FEE_KEY].value,
},
);

Expand All @@ -145,8 +157,13 @@ export async function start(zcf) {
const collateralBrand = zcf.getBrandForIssuer(collateralIssuer);
assert(!collateralTypes.has(collateralBrand));

const poolGovernor = makePoolGovernor(loanParams, rates);
const poolParamManager = makePoolParamManager(loanParams, rates);
assert(!poolGovernors.has(collateralBrand));
const poolGovernor = await E(governorPublic).governContract(
zcf.getInstance(),
poolParamManager,
'poolParams',
);
poolGovernors.init(collateralBrand, poolGovernor);

const { creatorFacet: liquidationFacet } = await E(zoe).startInstance(
Expand Down Expand Up @@ -242,7 +259,7 @@ export async function start(zcf) {
runMint,
collateralBrand,
priceAuthority,
poolGovernor.getParams,
poolParamManager.getParams,
reallocateReward,
timerService,
liquidationStrategy,
Expand Down Expand Up @@ -272,7 +289,7 @@ export async function start(zcf) {
const { brand: brandIn } = collateralAmount;
assert(
collateralTypes.has(brandIn),
details`Not a supported collateral type ${brandIn}`,
X`Not a supported collateral type ${brandIn}`,
);
/** @type {VaultManager} */
const mgr = collateralTypes.get(brandIn);
Expand Down Expand Up @@ -347,7 +364,7 @@ export async function start(zcf) {
getRunIssuer() {
return runIssuer;
},
getFeeParams: feeGovernor.getParams,
getFeeParams: feeParams.getParams,
});

const { makeCollectFeesInvitation } = makeMakeCollectFeesInvitation(
Expand Down
8 changes: 4 additions & 4 deletions packages/treasury/src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
* @property {() => Instance} getAMM
* @property {() => Promise<Array<Collateral>>} getCollaterals
* @property {() => Payment} getBootstrapPayment
* @property {() => ParamManagerFull} getFeeGovernor
* @property {() => ParamManagerFull} getPoolGovernor
* @property {() => ContractGovernor} getFeeGovernor
* @property {(Brand) => ContractGovernor} getPoolGovernor
*/

/**
Expand Down Expand Up @@ -193,14 +193,14 @@
*/

/**
* @typedef {Object} FeeGovernor
* @typedef {Object} FeeParamManager
* @property {() => Record<Keyword,ParamDescription>} getParams
* @property {(bigint) => void} updateProtocolFee
* @property {(bigint) => void} updatePoolFee
*/

/**
* @typedef {Object} PoolGovernor
* @typedef {Object} PoolParamManager
* @property {() => Record<Keyword,ParamDescription>} getParams
* @property {(bigint) => void} updateChargingPeriod
* @property {(bigint) => void} updateRecordingPeriod
Expand Down
68 changes: 68 additions & 0 deletions packages/treasury/test/test-bootstrapPayment.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,20 @@ import fakeVatAdmin from '@agoric/zoe/tools/fakeVatAdmin';
import { makeZoe } from '@agoric/zoe';
import buildManualTimer from '@agoric/zoe/tools/manualTimer';
import { AmountMath } from '@agoric/ertp';
import { governedParameterTerms } from '../src/params';

const stablecoinRoot = `${__dirname}/../src/stablecoinMachine.js`;
const liquidationRoot = `${__dirname}/../src/liquidateMinimum.js`;

const autoswapRoot = require.resolve(
'@agoric/zoe/src/contracts/multipoolAutoswap/multipoolAutoswap',
);
const governanceRoot = require.resolve(
'@agoric/governance/src/contractGovernor',
);
const registrarRoot = require.resolve(
'@agoric/governance/src/committeeRegistrar',
);

const makeInstall = async (root, zoe) => {
const bundle = await bundleSource(root);
Expand All @@ -26,11 +34,34 @@ const makeInstall = async (root, zoe) => {
return installationP;
};

const setupGovernor = async (
zoe,
registrarInstall,
registrarTerms,
governanceInstall,
) => {
const { instance: registrarInstance } = await E(zoe).startInstance(
registrarInstall,
{},
registrarTerms,
);

const governorTerms = { registrarInstance };
const { instance: governorInstance } = await E(zoe).startInstance(
governanceInstall,
{},
governorTerms,
);
return governorInstance;
};

test('bootstrap payment', async t => {
const zoe = makeZoe(fakeVatAdmin);
const autoswapInstall = await makeInstall(autoswapRoot, zoe);
const stablecoinInstall = await makeInstall(stablecoinRoot, zoe);
const liquidationInstall = await makeInstall(liquidationRoot, zoe);
const registrarInstall = await makeInstall(registrarRoot, zoe);
const governanceInstall = await makeInstall(governanceRoot, zoe);

const loanParams = {
chargingPeriod: 2n,
Expand All @@ -39,6 +70,15 @@ test('bootstrap payment', async t => {
protocolFee: 6n,
};
const manualTimer = buildManualTimer(console.log);

const registrarTerms = { committeeName: 'bandOfAngels', committeeSize: 5 };
const governorInstance = await setupGovernor(
zoe,
registrarInstall,
registrarTerms,
governanceInstall,
);

// This test value is not a statement about the actual value to
// be minted
const bootstrapPaymentValue = 20000n * 10n ** 6n;
Expand All @@ -53,6 +93,8 @@ test('bootstrap payment', async t => {
loanParams,
timerService: manualTimer,
liquidationInstall,
electionManager: governorInstance,
governedParams: governedParameterTerms,

bootstrapPaymentValue,
},
Expand All @@ -79,6 +121,8 @@ test('bootstrap payment - only minted once', async t => {
const autoswapInstall = await makeInstall(autoswapRoot, zoe);
const stablecoinInstall = await makeInstall(stablecoinRoot, zoe);
const liquidationInstall = await makeInstall(liquidationRoot, zoe);
const registrarInstall = await makeInstall(registrarRoot, zoe);
const governanceInstall = await makeInstall(governanceRoot, zoe);

const loanParams = {
chargingPeriod: 2n,
Expand All @@ -87,6 +131,15 @@ test('bootstrap payment - only minted once', async t => {
protocolFee: 6n,
};
const manualTimer = buildManualTimer(console.log);

const registrarTerms = { committeeName: 'bandOfAngels', committeeSize: 5 };
const governorInstance = await setupGovernor(
zoe,
registrarInstall,
registrarTerms,
governanceInstall,
);

// This test value is not a statement about the actual value to
// be minted
const bootstrapPaymentValue = 20000n * 10n ** 6n;
Expand All @@ -101,6 +154,8 @@ test('bootstrap payment - only minted once', async t => {
loanParams,
timerService: manualTimer,
liquidationInstall,
electionManager: governorInstance,
governedParams: governedParameterTerms,

bootstrapPaymentValue,
},
Expand Down Expand Up @@ -136,6 +191,8 @@ test('bootstrap payment - default value is 0n', async t => {
const autoswapInstall = await makeInstall(autoswapRoot, zoe);
const stablecoinInstall = await makeInstall(stablecoinRoot, zoe);
const liquidationInstall = await makeInstall(liquidationRoot, zoe);
const registrarInstall = await makeInstall(registrarRoot, zoe);
const governanceInstall = await makeInstall(governanceRoot, zoe);

const loanParams = {
chargingPeriod: 2n,
Expand All @@ -144,6 +201,15 @@ test('bootstrap payment - default value is 0n', async t => {
protocolFee: 6n,
};
const manualTimer = buildManualTimer(console.log);

const registrarTerms = { committeeName: 'bandOfAngels', committeeSize: 5 };
const governorInstance = await setupGovernor(
zoe,
registrarInstall,
registrarTerms,
governanceInstall,
);

const { creatorFacet: stablecoinMachine, instance } = await E(
zoe,
).startInstance(
Expand All @@ -155,6 +221,8 @@ test('bootstrap payment - default value is 0n', async t => {
loanParams,
timerService: manualTimer,
liquidationInstall,
electionManager: governorInstance,
governedParams: governedParameterTerms,
},
);

Expand Down
Loading

0 comments on commit a9ad9ab

Please sign in to comment.