Skip to content

Commit

Permalink
fix: use atomicTransfers rather than stagings. (#6577)
Browse files Browse the repository at this point in the history
* refactor: use atomicRearrange rather than stagings

* refactor: review suggestion

* refactor: more review suggestions

* refactpr: comment
  • Loading branch information
erights authored Dec 13, 2022
1 parent a2ecdec commit 65d3f14
Show file tree
Hide file tree
Showing 35 changed files with 530 additions and 300 deletions.
6 changes: 3 additions & 3 deletions packages/inter-protocol/src/collectFees.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { atomicTransfer } from '@agoric/zoe/src/contractSupport';

/**
* Provide shared support for providing access to fees from a service contract.
*
Expand All @@ -14,9 +16,7 @@ export const makeMakeCollectFeesInvitation = (
) => {
const collectFees = seat => {
const amount = feeSeat.getAmountAllocated(keyword, feeBrand);
feeSeat.decrementBy(harden({ [keyword]: amount }));
seat.incrementBy(harden({ Fee: amount }));
zcf.reallocate(seat, feeSeat);
atomicTransfer(zcf, feeSeat, seat, { [keyword]: amount }, { Fee: amount });

seat.exit();
return `paid out ${amount.value}`;
Expand Down
1 change: 1 addition & 0 deletions packages/inter-protocol/src/contractSupport.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export const assertOnlyKeys = (proposal, keys) => {
* the gain and a loss on the `fromSeat`. The gain/loss are typically from the
* give/want respectively of a proposal. The `key` is the allocation keyword.
*
* @deprecated Use atomicRearrange instead
* @param {ZCFSeat} fromSeat
* @param {ZCFSeat} toSeat
* @param {Amount} fromLoses
Expand Down
8 changes: 5 additions & 3 deletions packages/inter-protocol/src/interchainPool.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { E, Far } from '@endo/far';
import { AmountMath, AssetKind, makeIssuerKit } from '@agoric/ertp';
import { offerTo } from '@agoric/zoe/src/contractSupport/index.js';
import {
offerTo,
atomicTransfer,
} from '@agoric/zoe/src/contractSupport/index.js';
import { MIN_INITIAL_POOL_LIQUIDITY_KEY } from './vpool-xyk-amm/params.js';

const { Fail, quote: q } = assert;
Expand Down Expand Up @@ -87,8 +90,7 @@ export const start = (zcf, { bankManager }) => {
},
});

seat2.incrementBy(seat.decrementBy(harden({ Central: centralAmt })));
zcf.reallocate(seat, seat2);
atomicTransfer(zcf, seat, seat2, { Central: centralAmt });

const invitation = await E(ammPub).addPoolInvitation();
const { userSeatPromise, deposited } = await offerTo(
Expand Down
65 changes: 24 additions & 41 deletions packages/inter-protocol/src/psm/psm.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
ceilMultiplyBy,
floorDivideBy,
floorMultiplyBy,
atomicRearrange,
} from '@agoric/zoe/src/contractSupport/index.js';
import { Far } from '@endo/marshal';
import {
Expand Down Expand Up @@ -49,21 +50,6 @@ const { Fail } = assert;
* ever given by this contract
*/

/**
* Stage a transfer of a single asset from one seat to another, with an optional
* remapping of the Keywords. Check that the remapping is for the same amount.
*
* @param {ZCFSeat} from
* @param {ZCFSeat} to
* @param {AmountKeywordRecord} txFrom
* @param {AmountKeywordRecord} txTo
*/
const stageTransfer = (from, to, txFrom, txTo = txFrom) => {
assert(AmountMath.isEqual(Object.values(txFrom)[0], Object.values(txTo)[0]));
from.decrementBy(txFrom);
to.incrementBy(txTo);
};

/** @typedef {import('@agoric/vat-data').Baggage} Baggage */

/**
Expand Down Expand Up @@ -177,24 +163,18 @@ export const start = async (zcf, privateArgs, baggage) => {
const maxAnchor = floorMultiplyBy(afterFee, anchorPerMinted);
AmountMath.isGTE(maxAnchor, wanted) ||
Fail`wanted ${wanted} is more than ${given} minus fees ${fee}`;
try {
stageTransfer(seat, stage, { In: afterFee }, { Minted: afterFee });
stageTransfer(seat, feePool, { In: fee }, { Minted: fee });
stageTransfer(
anchorPool,
seat,
{ Anchor: maxAnchor },
{ Out: maxAnchor },
);
zcf.reallocate(seat, anchorPool, stage, feePool);
burnMinted(afterFee);
} catch (e) {
stage.clear();
anchorPool.clear();
feePool.clear();
// TODO(#6116) someday, reallocate should guarantee that this case cannot happen
throw e;
}
atomicRearrange(
zcf,
harden([
[seat, stage, { In: afterFee }, { Minted: afterFee }],
[seat, feePool, { In: fee }, { Minted: fee }],
[anchorPool, seat, { Anchor: maxAnchor }, { Out: maxAnchor }],
]),
);
// The treatment of `burnMinted` here is different than the
// one immediately below. This `burnMinted`
// happen only if the `atomicRearrange` does *not* throw.
burnMinted(afterFee);
totalAnchorProvided = AmountMath.add(totalAnchorProvided, maxAnchor);
};

Expand All @@ -212,15 +192,18 @@ export const start = async (zcf, privateArgs, baggage) => {
Fail`wanted ${wanted} is more than ${given} minus fees ${fee}`;
mintMinted(asStable);
try {
stageTransfer(seat, anchorPool, { In: given }, { Anchor: given });
stageTransfer(stage, seat, { Minted: afterFee }, { Out: afterFee });
stageTransfer(stage, feePool, { Minted: fee });
zcf.reallocate(seat, anchorPool, stage, feePool);
atomicRearrange(
zcf,
harden([
[seat, anchorPool, { In: given }, { Anchor: given }],
[stage, seat, { Minted: afterFee }, { Out: afterFee }],
[stage, feePool, { Minted: fee }],
]),
);
} catch (e) {
stage.clear();
anchorPool.clear();
feePool.clear();
// TODO(#6116) someday, reallocate should guarantee that this case cannot happen
// The treatment of `burnMinted` here is different than the
// one immediately above. This `burnMinted`
// happens only if the `atomicRearrange` *does* throw.
burnMinted(asStable);
throw e;
}
Expand Down
42 changes: 20 additions & 22 deletions packages/inter-protocol/src/reserve/assetReserve.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { E, Far } from '@endo/far';
import { AmountMath } from '@agoric/ertp';
import { handleParamGovernance, ParamTypes } from '@agoric/governance';
import { offerTo } from '@agoric/zoe/src/contractSupport/index.js';
import {
offerTo,
atomicTransfer,
} from '@agoric/zoe/src/contractSupport/index.js';
import { provideDurableMapStore, vivifyKindMulti } from '@agoric/vat-data';

import { AMM_INSTANCE } from './params.js';
Expand Down Expand Up @@ -253,10 +256,14 @@ const start = async (zcf, privateArgs, baggage) => {
} = seat.getProposal();

const collateralKeyword = getKeywordForBrand(amountIn.brand);
seat.decrementBy(harden({ Collateral: amountIn }));
collateralSeat.incrementBy(harden({ [collateralKeyword]: amountIn }));

zcf.reallocate(collateralSeat, seat);
atomicTransfer(
zcf,
seat,
collateralSeat,
{ Collateral: amountIn },
{ [collateralKeyword]: amountIn },
);
seat.exit();

trace('received collateral', amountIn);
Expand Down Expand Up @@ -333,14 +340,9 @@ const start = async (zcf, privateArgs, baggage) => {
const offerToSeat = feeMint.mintGains(harden({ Fee: fee }));
state.totalFeeMinted = AmountMath.add(state.totalFeeMinted, fee);

offerToSeat.incrementBy(
collateralSeat.decrementBy(
harden({
[collateralKeyword]: collateral,
}),
),
);
zcf.reallocate(collateralSeat, offerToSeat);
atomicTransfer(zcf, collateralSeat, offerToSeat, {
[collateralKeyword]: collateral,
});

// Add Fee tokens and collateral to the AMM
const invitation = await E(
Expand Down Expand Up @@ -368,17 +370,13 @@ const start = async (zcf, privateArgs, baggage) => {
const liquidityAmount = offerToSeat.getCurrentAllocation();
const liquidityKeyword = makeLiquidityKeyword(collateralKeyword);

offerToSeat.decrementBy(
harden({
Liquidity: liquidityAmount.Liquidity,
}),
);
collateralSeat.incrementBy(
harden({
[liquidityKeyword]: liquidityAmount.Liquidity,
}),
atomicTransfer(
zcf,
offerToSeat,
collateralSeat,
{ Liquidity: liquidityAmount.Liquidity },
{ [liquidityKeyword]: liquidityAmount.Liquidity },
);
zcf.reallocate(offerToSeat, collateralSeat);
updateMetrics({ state });
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
natSafeMath as NatMath,
ceilMultiplyBy,
oneMinus,
atomicTransfer,
} from '@agoric/zoe/src/contractSupport/index.js';
import { AmountMath } from '@agoric/ertp';
import { Far } from '@endo/marshal';
Expand Down Expand Up @@ -321,10 +322,7 @@ const start = async zcf => {
const penaltyPaid = AmountMath.min(penalty, debtPaid);

// Allocate penalty portion of proceeds to a seat that will hold it for transfer to reserve
penaltyPoolSeat.incrementBy(
debtorSeat.decrementBy(harden({ Out: penaltyPaid })),
);
zcf.reallocate(penaltyPoolSeat, debtorSeat);
atomicTransfer(zcf, debtorSeat, penaltyPoolSeat, { Out: penaltyPaid });

debtorSeat.exit();
trace('exit seat');
Expand Down
6 changes: 2 additions & 4 deletions packages/inter-protocol/src/vaultFactory/liquidateMinimum.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { E } from '@endo/eventual-send';
import {
ceilMultiplyBy,
offerTo,
atomicTransfer,
} from '@agoric/zoe/src/contractSupport/index.js';
import { AmountMath } from '@agoric/ertp';
import { Far } from '@endo/marshal';
Expand Down Expand Up @@ -73,10 +74,7 @@ const start = async zcf => {
const penaltyPaid = AmountMath.min(penalty, debtPaid);

// Allocate penalty portion of proceeds to a seat that will hold it for transfer to reserve
penaltyPoolSeat.incrementBy(
debtorSeat.decrementBy(harden({ Out: penaltyPaid })),
);
zcf.reallocate(penaltyPoolSeat, debtorSeat);
atomicTransfer(zcf, debtorSeat, penaltyPoolSeat, { Out: penaltyPaid });

debtorSeat.exit();
};
Expand Down
9 changes: 5 additions & 4 deletions packages/inter-protocol/src/vaultFactory/vault.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
makeRatioFromAmounts,
ceilMultiplyBy,
floorMultiplyBy,
atomicTransfer,
} from '@agoric/zoe/src/contractSupport/index.js';
import { AmountMath } from '@agoric/ertp';
import {
Expand Down Expand Up @@ -398,15 +399,15 @@ const helperBehavior = {
Fail`Offer ${given} is not sufficient to pay off debt ${debt}`;

// Return any overpayment
seat.incrementBy(vaultSeat.decrementBy(vaultSeat.getCurrentAllocation()));
zcf.reallocate(seat, vaultSeat);
atomicTransfer(zcf, vaultSeat, seat, vaultSeat.getCurrentAllocation());

state.manager.burnAndRecord(debt, seat);
} else if (phase === Phase.LIQUIDATED) {
// Simply reallocate vault assets to the offer seat.
// Don't take anything from the offer, even if vault is underwater.
// TODO verify that returning Minted here doesn't mess up debt limits
seat.incrementBy(vaultSeat.decrementBy(vaultSeat.getCurrentAllocation()));
zcf.reallocate(seat, vaultSeat);

atomicTransfer(zcf, vaultSeat, seat, vaultSeat.getCurrentAllocation());
} else {
throw new Error('only active and liquidated vaults can be closed');
}
Expand Down
10 changes: 4 additions & 6 deletions packages/inter-protocol/src/vaultFactory/vaultManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
getAmountOut,
makeRatio,
makeRatioFromAmounts,
atomicTransfer,
} from '@agoric/zoe/src/contractSupport/index.js';
import { E } from '@endo/eventual-send';
import { unitAmount } from '@agoric/zoe/src/contractSupport/priceQuote.js';
Expand Down Expand Up @@ -537,12 +538,9 @@ const helperBehavior = {
// it. We could hold it until it crosses some threshold, then sell it
// to the AMM, or we could transfer it to the reserve. At least it's
// visible in the accounting.
vaultSeat.decrementBy(
state.retainedCollateralSeat.incrementBy({
Collateral: collateralPost,
}),
);
zcf.reallocate(vaultSeat, state.retainedCollateralSeat);
atomicTransfer(zcf, vaultSeat, state.retainedCollateralSeat, {
Collateral: collateralPost,
});
}

// Reduce totalCollateral by collateralPre, since all the collateral was
Expand Down
16 changes: 12 additions & 4 deletions packages/inter-protocol/src/vpool-xyk-amm/addPool.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { E } from '@endo/eventual-send';
import { AmountMath, AssetKind } from '@agoric/ertp';
import { assertProposalShape } from '@agoric/zoe/src/contractSupport/index.js';
import {
assertProposalShape,
atomicTransfer,
} from '@agoric/zoe/src/contractSupport/index.js';

import { definePoolKind } from './pool.js';

Expand Down Expand Up @@ -173,10 +176,15 @@ export const makeAddPoolInvitation = (
// transfer minPoolLiquidity in tokens from the funder to the reserve.
helper.addLiquidityInternal(seat, secondaryAmount, centralAmount);

seat.decrementBy({ Liquidity: minLiqAmount });
const { zcfSeat: reserveLiquidityTokenSeat } = zcf.makeEmptySeatKit();
reserveLiquidityTokenSeat.incrementBy({ [liquidityKeyword]: minLiqAmount });
zcf.reallocate(reserveLiquidityTokenSeat, seat);
atomicTransfer(
zcf,
seat,
reserveLiquidityTokenSeat,
{ Liquidity: minLiqAmount },
{ [liquidityKeyword]: minLiqAmount },
);

seat.exit();
pool.updateState();

Expand Down
26 changes: 18 additions & 8 deletions packages/inter-protocol/src/vpool-xyk-amm/doublePool.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { AmountMath } from '@agoric/ertp';
import {
atomicRearrange,
fromOnly,
toOnly,
} from '@agoric/zoe/src/contractSupport/index.js';
import { Far } from '@endo/marshal';
import { makeFeeRatio } from './constantProduct/calcFees.js';
import {
Expand Down Expand Up @@ -55,15 +60,20 @@ export const makeDoublePool = (
const inPoolSeat = collateralInPool.getPoolSeat();
const outPoolSeat = collateralOutPool.getPoolSeat();

seat.decrementBy(harden({ In: prices.swapperGives }));
inPoolSeat.decrementBy(harden({ Central: prices.inPoolDecrement }));
outPoolSeat.decrementBy(harden({ Secondary: prices.outPoolDecrement }));
seat.incrementBy(harden({ Out: prices.swapperGets }));
inPoolSeat.incrementBy(harden({ Secondary: prices.inPoolIncrement }));
outPoolSeat.incrementBy(harden({ Central: prices.outPoolIncrement }));
feeSeat.incrementBy(harden({ Fee: prices.protocolFee }));
atomicRearrange(
zcf,
harden([
fromOnly(seat, { In: prices.swapperGives }),
fromOnly(inPoolSeat, { Central: prices.inPoolDecrement }),
fromOnly(outPoolSeat, { Secondary: prices.outPoolDecrement }),

toOnly(seat, { Out: prices.swapperGets }),
toOnly(inPoolSeat, { Secondary: prices.inPoolIncrement }),
toOnly(outPoolSeat, { Central: prices.outPoolIncrement }),
toOnly(feeSeat, { Fee: prices.protocolFee }),
]),
);

zcf.reallocate(outPoolSeat, inPoolSeat, feeSeat, seat);
seat.exit();
collateralInPool.updateState();
collateralOutPool.updateState();
Expand Down
Loading

0 comments on commit 65d3f14

Please sign in to comment.