Skip to content

Commit

Permalink
test: add a test that new VM was added and can issue loans
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris-Hibbert committed Oct 13, 2021
1 parent e845cdc commit 08d6304
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 20 deletions.
44 changes: 29 additions & 15 deletions packages/treasury/src/addType.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import { AmountMath } from '@agoric/ertp';
import { makeLiquidationStrategy } from './liquidateMinimum';
import { makeVaultManager } from './vaultManager';
import { makePoolParamManager } from './params';
import { makeTracer } from './makeTracer';
import { makeTracer } from './makeTracer.js';

const { details: X } = assert;

const trace = makeTracer('ST');

Expand Down Expand Up @@ -42,7 +44,7 @@ const makeMakeAddTypeInvitation = (
*
* @type {ReallocateReward}
*/
function reallocateReward(amount, fromSeat, otherSeat = undefined) {
const reallocateReward = (amount, fromSeat, otherSeat = undefined) => {
rewardPoolSeat.incrementBy(
fromSeat.decrementBy({
RUN: amount,
Expand All @@ -53,10 +55,13 @@ const makeMakeAddTypeInvitation = (
} else {
zcf.reallocate(rewardPoolSeat, fromSeat);
}
}
};

const collateralBrand = zcf.getBrandForIssuer(collateralIssuer);
assert(!collateralTypes.has(collateralBrand));
assert(
!collateralTypes.has(collateralBrand),
X`Each type of collateral may only be added to Treasury once: ${collateralBrand}`,
);

const poolParamManager = makePoolParamManager(loanParams, rates);
poolParamManagers.init(collateralBrand, poolParamManager);
Expand All @@ -69,7 +74,7 @@ const makeMakeAddTypeInvitation = (
{ autoswap: autoswapAPI },
);

async function addTypeHook(seat) {
const addTypeHook = async seat => {
assertProposalShape(seat, {
give: { Collateral: null },
want: { Governance: null },
Expand All @@ -78,7 +83,11 @@ const makeMakeAddTypeInvitation = (
give: { Collateral: collateralIn },
want: { Governance: _govOut }, // ownership of the whole stablecoin machine
} = seat.getProposal();
assert(!collateralTypes.has(collateralBrand));
assert(
!collateralTypes.has(collateralBrand),
X`Each type of collateral may only be added to Treasury once: ${collateralBrand}`,
);

// initialPrice is in rates, but only used at creation, so not in governor
const runAmount = ceilMultiplyBy(collateralIn, rates.initialPrice);
// arbitrarily, give governance tokens equal to RUN tokens
Expand Down Expand Up @@ -163,21 +172,22 @@ const makeMakeAddTypeInvitation = (
);
collateralTypes.init(collateralBrand, vm);
return vm;
}
};

return zcf.makeInvitation(addTypeHook, 'AddCollateralType');
};
};

const makeAddTypeNoAmm = (
const makeMakeAddTypeNoAmm = (
zcf,
poolParamManagers,
rewardPoolSeat,
issuers,
autoswapAPI,
collateralTypes,
runKit,
) => {
// TODO(hibbert) check that there's a corresponding AMM pool

// We process only one offer per collateralType. They must tell us the
// dollar value of their collateral, and we create that many RUN.
// collateralKeyword = 'aEth'
Expand All @@ -197,7 +207,7 @@ const makeAddTypeNoAmm = (
*
* @type {ReallocateReward}
*/
function reallocateReward(amount, fromSeat, otherSeat = undefined) {
const reallocateReward = (amount, fromSeat, otherSeat = undefined) => {
rewardPoolSeat.incrementBy(
fromSeat.decrementBy({
RUN: amount,
Expand All @@ -208,10 +218,13 @@ const makeAddTypeNoAmm = (
} else {
zcf.reallocate(rewardPoolSeat, fromSeat);
}
}
};

const collateralBrand = zcf.getBrandForIssuer(collateralIssuer);
assert(!collateralTypes.has(collateralBrand));
assert(
!collateralTypes.has(collateralBrand),
X`Each type of collateral may only be added to Treasury once: ${collateralBrand}`,
);

const poolParamManager = makePoolParamManager(loanParams, rates);
poolParamManagers.init(collateralBrand, poolParamManager);
Expand All @@ -220,7 +233,7 @@ const makeAddTypeNoAmm = (
zcf.getZoeService(),
).startInstance(
liquidationInstall,
{ RUN: issuers.run },
{ RUN: runKit.issuer },
{ autoswap: autoswapAPI },
);

Expand All @@ -238,12 +251,13 @@ const makeAddTypeNoAmm = (
timerService,
liquidationStrategy,
);

collateralTypes.init(collateralBrand, vm);
return vm;
};
};

harden(makeMakeAddTypeInvitation);
harden(makeAddTypeNoAmm);
harden(makeMakeAddTypeNoAmm);

export { makeMakeAddTypeInvitation, makeAddTypeNoAmm };
export { makeMakeAddTypeInvitation, makeMakeAddTypeNoAmm };
16 changes: 13 additions & 3 deletions packages/treasury/src/stablecoinMachine.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import {
governedParameterTerms as governedParameterLocal,
ParamKey,
} from './params.js';
import { makeAddTypeNoAmm, makeMakeAddTypeInvitation } from './addType';
import { makeMakeAddTypeNoAmm, makeMakeAddTypeInvitation } from './addType';

const { quote: q, details: X } = assert;

Expand Down Expand Up @@ -240,7 +240,7 @@ export async function start(zcf, privateArgs) {
};

const getParamState = paramDesc => {
switch (paramDesc.keyl) {
switch (paramDesc.key) {
case ParamKey.FEE:
return feeParams.getParam(paramDesc.parameterName);
case ParamKey.POOL:
Expand Down Expand Up @@ -291,18 +291,28 @@ export async function start(zcf, privateArgs) {
},
});

const runKit = { brand: runBrand, mint: runMint, issuer: runIssuer };
const makeAddTypeInvitation = makeMakeAddTypeInvitation(
zcf,
poolParamManagers,
rewardPoolSeat,
autoswapAPI,
collateralTypes,
{ brand: runBrand, mint: runMint, issuer: runIssuer },
runKit,
{ brand: govBrand, mint: govMint },
);
const makeAddTypeNoAmm = makeMakeAddTypeNoAmm(
zcf,
poolParamManagers,
rewardPoolSeat,
autoswapAPI,
collateralTypes,
runKit,
);

/** @type {StablecoinMachine} */
const stablecoinMachine = Far('stablecoin machine', {
makeAddTypeNoAmm,
makeAddTypeInvitation,
getAMM() {
return autoswapInstance;
Expand Down
55 changes: 53 additions & 2 deletions packages/treasury/test/test-stablecoin.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { makeTracer } from '../src/makeTracer.js';
import { SECONDS_PER_YEAR } from '../src/interest.js';
import { VaultState } from '../src/vault.js';

import { governedParameterTerms } from '../src/params.js';
import { governedParameterTerms, ParamKey } from '../src/params.js';

const stablecoinRoot = '../src/stablecoinMachine.js';
const liquidationRoot = '../src/liquidateMinimum.js';
Expand All @@ -39,6 +39,7 @@ const committeeRoot = '@agoric/governance/src/committee.js';
const voteCounterRoot = '@agoric/governance/src/binaryVoteCounter.js';

const trace = makeTracer('TestST');
const { quote: q } = assert;

const BASIS_POINTS = 10000n;
const PERCENT = 100n;
Expand Down Expand Up @@ -251,7 +252,6 @@ async function setupServices(
const s = { stablecoinMachine, lender };
const { runIssuerRecord, govIssuerRecord, autoswap: autoswapAPI } = testJig;
const issuers = { run: runIssuerRecord, gov: govIssuerRecord };

const quoteMint = makeIssuerKit('quote', AssetKind.SET).mint;

// priceAuthority needs the RUN brand, which isn't available until the
Expand Down Expand Up @@ -1810,3 +1810,54 @@ test('close loan', async t => {
{},
);
});

test('stablecoin add collateral no new AMM pool', async t => {
const loanParams = {
chargingPeriod: 2n,
recordingPeriod: 6n,
poolFee: 24n,
protocolFee: 6n,
};
const {
aethKit: { brand: aethBrand, mint: aethMint, issuer: aethIssuer },
} = setupAssets();

const services = await setupServices(
loanParams,
[500n, 1500n],
AmountMath.make(90n, aethBrand),
aethBrand,
{ committeeName: 'TheCabal', committeeSize: 5 },
);
const { brand: runBrand, issuer: runIssuer } = services.issuers.run;
const { stablecoinMachine, lender } = services.stablecoin;

const rates = harden({
initialMargin: makeRatio(120n, runBrand),
liquidationMargin: makeRatio(105n, runBrand),
interestRate: makeRatio(100n, runBrand, BASIS_POINTS),
loanFee: makeRatio(530n, runBrand, BASIS_POINTS),
});

await E(stablecoinMachine).makeAddTypeNoAmm(aethIssuer, 'Doubloon', rates);

const collateralAmount = AmountMath.make(aethBrand, 1500n);
const loanAmount = AmountMath.make(500n, runBrand);
const loanSeat = await E(services.zoe).offer(
E(lender).makeLoanInvitation(),
harden({
give: { Collateral: collateralAmount },
want: { RUN: loanAmount },
}),
harden({
Collateral: await E(aethMint).mintPayment(collateralAmount),
}),
);

const loanProceeds = await E.get(E(loanSeat).getPayouts()).RUN;

t.deepEqual(await E(runIssuer).getAmountOf(loanProceeds), loanAmount);
// The AMM pool hasn't been initialized, but now we have some RUN that we
// could use to add liquidity to the pool. The AMM is only needed for
// liquidation
});

0 comments on commit 08d6304

Please sign in to comment.