Skip to content

Commit

Permalink
Merge pull request #2761 from Agoric/mfig-bootstrap-collateral
Browse files Browse the repository at this point in the history
feat: add collateralConfig to issuer entries and enact
  • Loading branch information
michaelfig authored Mar 30, 2021
2 parents 11285e7 + 43992e3 commit 151a394
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 60 deletions.
2 changes: 1 addition & 1 deletion packages/agoric-cli/integration-tests/test-workflow.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { spawn } from 'child_process';

import { makePspawn } from '../lib/helpers';

const TIMEOUT_SECONDS = 2 * 60;
const TIMEOUT_SECONDS = 8 * 60;

// To keep in sync with https://agoric.com/documentation/getting-started/

Expand Down
124 changes: 108 additions & 16 deletions packages/cosmic-swingset/lib/ag-solo/vats/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,19 @@ import { installOnChain as installEconomyOnChain } from '@agoric/treasury/bundle
// has been run to update gci.js
import { makePluginManager } from '@agoric/swingset-vat/src/vats/plugin-manager';
import { assert, details as X } from '@agoric/assert';
import { makeRatio } from '@agoric/zoe/src/contractSupport';
import { amountMath } from '@agoric/ertp';
import { GCI } from './gci';
import { makeBridgeManager } from './bridge';
import { makeNameHubKit } from './nameHub';
import { CENTRAL_ISSUER_NAME, fakeIssuerNameToRecord } from './issuers';
import { CENTRAL_ISSUER_NAME, fakeIssuerEntries } from './issuers';

const NUM_IBC_PORTS = 3;
const QUOTE_INTERVAL = 30;

const PERCENT_DENOM = 100n;
const BASIS_POINTS_DENOM = 10000n;

console.debug(`loading bootstrap.js`);

// Used for coordinating on an index in comms for the provisioning service
Expand Down Expand Up @@ -63,7 +68,7 @@ export function buildRootObject(vatPowers, vatParameters) {
E(vats.registrar).getSharedRegistrar(),
E(vats.board).getBoard(),
E(vats.timer).createTimerService(timerDevice),
E(vats.zoe).buildZoe(vatAdminSvc),
/** @type {ZoeService} */ (E(vats.zoe).buildZoe(vatAdminSvc)),
E(vats.host).makeHost(),
E(vats.priceAuthority).makePriceAuthority(),
]);
Expand Down Expand Up @@ -92,7 +97,7 @@ export function buildRootObject(vatPowers, vatParameters) {
);

// Install the economy, giving it access to the name admins we made.
await installEconomyOnChain({
return installEconomyOnChain({
agoricNames,
board,
chainTimerService,
Expand All @@ -103,8 +108,10 @@ export function buildRootObject(vatPowers, vatParameters) {
}

// Now we can bootstrap the economy!
await installEconomy();
const centralIssuer = await E(agoricNames).lookup('issuer', 'MOE');
const treasuryCreator = await installEconomy();
const [centralIssuer, centralBrand] = await Promise.all(
['issuer', 'brand'].map(hub => E(agoricNames).lookup(hub, 'MOE')),
);

const CENTRAL_ISSUER_ENTRY = [
CENTRAL_ISSUER_NAME,
Expand All @@ -116,22 +123,31 @@ export function buildRootObject(vatPowers, vatParameters) {
},
];

const issuerNameToRecord = noFakeCurrencies
? new Map()
: fakeIssuerNameToRecord;
issuerNameToRecord.set(...CENTRAL_ISSUER_ENTRY);
/** @type {Store<string, import('./issuers').IssuerInitializationRecord>} */
const issuerNameToRecord = makeStore();
if (!noFakeCurrencies) {
fakeIssuerEntries.map(entry => issuerNameToRecord.init(...entry));
}
issuerNameToRecord.init(...CENTRAL_ISSUER_ENTRY);

const issuerNames = [...issuerNameToRecord.keys()];
const issuers = await Promise.all(
issuerNames.map(issuerName => {
issuerNames.map(async issuerName => {
const record = issuerNameToRecord.get(issuerName);
if (record.issuer !== undefined) {
return record.issuer;
}
return E(vats.mints).makeMintAndIssuer(
/** @type {Issuer} */
const issuer = await E(vats.mints).makeMintAndIssuer(
issuerName,
...(record.issuerArgs || []),
);
const brand = await E(issuer).getBrand();
issuerNameToRecord.set(
issuerName,
harden({ ...record, brand, issuer }),
);
return issuer;
}),
);

Expand Down Expand Up @@ -161,13 +177,13 @@ export function buildRootObject(vatPowers, vatParameters) {
);
};
await Promise.all(
issuers.map(async (issuer, i) => {
issuerNames.map(async issuerName => {
// Create priceAuthority pairs for centralIssuer based on the
// FakePriceAuthority.
console.debug(`Creating ${issuerNames[i]}-${CENTRAL_ISSUER_NAME}`);
const { fakeTradesGivenCentral } = issuerNameToRecord.get(
issuerNames[i],
);
console.debug(`Creating ${issuerName}-${CENTRAL_ISSUER_NAME}`);
const record = issuerNameToRecord.get(issuerName);
assert(record);
const { fakeTradesGivenCentral, issuer } = record;
if (!fakeTradesGivenCentral) {
return;
}
Expand All @@ -185,6 +201,79 @@ export function buildRootObject(vatPowers, vatParameters) {
}),
);

async function addAllCollateral() {
const govBrand = await E(agoricNames).lookup(
'brand',
'TreasuryGovernance',
);
return Promise.all(
issuerNames.map(async issuerName => {
const record = issuerNameToRecord.get(issuerName);
const config = record.collateralConfig;
if (!config) {
return undefined;
}
const rates = {
initialPrice: makeRatio(
config.initialPricePercent,
centralBrand,
PERCENT_DENOM,
record.brand,
),
initialMargin: makeRatio(config.initialMarginPercent, centralBrand),
liquidationMargin: makeRatio(
config.liquidationMarginPercent,
centralBrand,
),
interestRate: makeRatio(
config.interestRateBasis,
centralBrand,
BASIS_POINTS_DENOM,
),
loanFee: makeRatio(
config.loanFeeBasis,
centralBrand,
BASIS_POINTS_DENOM,
),
};

const addTypeInvitation = E(treasuryCreator).makeAddTypeInvitation(
record.issuer,
config.keyword,
rates,
);

const payments = E(vats.mints).mintInitialPayments(
[issuerName],
[config.collateralValue],
);
const payment = E.get(payments)[0];

const amount = await E(record.issuer).getAmountOf(payment);
const proposal = harden({
give: {
Collateral: amount,
},
want: {
// We just throw away our governance tokens.
Governance: amountMath.make(0n, govBrand),
},
});
const paymentKeywords = harden({
Collateral: payment,
});
const seat = E(zoe).offer(
addTypeInvitation,
proposal,
paymentKeywords,
);
const vaultManager = E(seat).getOfferResult();
return vaultManager;
}),
);
}
await addAllCollateral();

return Far('chainBundler', {
async createUserBundle(_nickname, address, powerFlags = []) {
// Bind to some fresh ports (unspecified name) on the IBC implementation
Expand All @@ -206,6 +295,9 @@ export function buildRootObject(vatPowers, vatParameters) {
if (powerFlags && powerFlags.includes('agoric.agoricNamesAdmin')) {
additionalPowers.agoricNamesAdmin = agoricNamesAdmin;
}
if (powerFlags && powerFlags.includes('agoric.treasuryCreator')) {
additionalPowers.treasuryCreator = treasuryCreator;
}

const payments = await E(vats.mints).mintInitialPayments(
issuerNames,
Expand Down
129 changes: 86 additions & 43 deletions packages/cosmic-swingset/lib/ag-solo/vats/issuers.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,99 @@

export const CENTRAL_ISSUER_NAME = 'MOE';

/** @typedef {number | bigint} Bigish */

/**
* @typedef {Object} CollateralConfig
* @property {string} keyword
* @property {Bigish} collateralValue
* @property {bigint} initialPricePercent
* @property {bigint} initialMarginPercent
* @property {bigint} liquidationMarginPercent
* @property {bigint} interestRateBasis
* @property {bigint} loanFeeBasis
*/

/**
* @typedef {Object} IssuerInitializationRecord
* @property {Issuer} [issuer]
* @property {Brand} [brand]
* @property {Array<any>} [issuerArgs]
* @property {CollateralConfig} [collateralConfig]
* @property {string} pursePetname
* @property {number} mintValue
* @property {Array<[number, number]>} [fakeTradesGivenCentral]
* @property {Bigish} mintValue
* @property {Array<[Bigish, Bigish]>} [fakeTradesGivenCentral]
*/

/** @type {Map<string, IssuerInitializationRecord>} */
export const fakeIssuerNameToRecord = new Map(
harden([
[
'$LINK',
{
issuerArgs: [undefined, { decimalPlaces: 6 }],
mintValue: 7 * 10 ** 6,
pursePetname: 'Oracle fee',
fakeTradesGivenCentral: [
[1000, 3000000],
[1000, 2500000],
[1000, 2750000],
],
/** @type {Array<[string, IssuerInitializationRecord]>} */
const fakeIssuerEntries = [
[
'$LINK',
{
issuerArgs: [undefined, { decimalPlaces: 18 }],
mintValue: 7n * 10n ** 18n,
collateralConfig: {
keyword: 'LINK',
collateralValue: 6000n * 10n ** 18n,
initialPricePercent: 125n,
initialMarginPercent: 150n,
liquidationMarginPercent: 125n,
interestRateBasis: 250n,
loanFeeBasis: 50n,
},
],
[
'moola',
{
mintValue: 1900,
pursePetname: 'Fun budget',
fakeTradesGivenCentral: [
[10, 1],
[13, 1],
[12, 1],
[18, 1],
[15, 1],
],
pursePetname: 'Oracle fee',
fakeTradesGivenCentral: [
[1000, 3000n * 10n ** 15n],
[1000, 2500n * 10n ** 15n],
[1000, 2750n * 10n ** 15n],
],
},
],
[
'moola',
{
mintValue: 1900,
collateralConfig: {
collateralValue: 74000,
keyword: 'Moola',
initialPricePercent: 150n,
initialMarginPercent: 150n,
liquidationMarginPercent: 120n,
interestRateBasis: 200n,
loanFeeBasis: 150n,
},
],
[
'simolean',
{
mintValue: 1900,
pursePetname: 'Nest egg',
fakeTradesGivenCentral: [
[2135, 50],
[2172, 50],
[2124, 50],
],
pursePetname: 'Fun budget',
fakeTradesGivenCentral: [
[10, 1],
[13, 1],
[12, 1],
[18, 1],
[15, 1],
],
},
],
[
'simolean',
{
mintValue: 1900,
collateralConfig: {
collateralValue: 96800,
keyword: 'Simolean',
initialPricePercent: 110n,
initialMarginPercent: 120n,
liquidationMarginPercent: 105n,
interestRateBasis: 100n,
loanFeeBasis: 225n,
},
],
]),
);
pursePetname: 'Nest egg',
fakeTradesGivenCentral: [
[2135, 50],
[2172, 50],
[2124, 50],
],
},
],
];

harden(fakeIssuerEntries);
export { fakeIssuerEntries };
2 changes: 2 additions & 0 deletions packages/treasury/bundles/install-on-chain.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,6 @@ export async function installOnChain({ agoricNames, board, chainTimerService, na
await Promise.all(
nameAdminUpdates.map(([nameAdmin, name, value]) => E(nameAdmin).update(name, value)),
);

return creatorFacet;
}

0 comments on commit 151a394

Please sign in to comment.