Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: fusdc advancer #10420

Merged
merged 3 commits into from
Nov 15, 2024
Merged

feat: fusdc advancer #10420

merged 3 commits into from
Nov 15, 2024

Conversation

0xpatrickdev
Copy link
Member

@0xpatrickdev 0xpatrickdev commented Nov 7, 2024

refs: #10390

Description

  • advancer performs balance check
  • advancer requests payment from LiquidityPool
  • advancer deposits payment in PoolAccount
  • advancer submits IBC transfer

Security Considerations

Deals with live payments and ensures they do not get lost during failure paths

Scaling Considerations

No new ones introduced

Documentation Considerations

Testing Considerations

Includes tests

Upgrade Considerations

NA, unreleased

@0xpatrickdev 0xpatrickdev changed the base branch from master to pc/fusdc-status-manager November 7, 2024 15:23
Copy link

cloudflare-workers-and-pages bot commented Nov 7, 2024

Deploying agoric-sdk with  Cloudflare Pages  Cloudflare Pages

Latest commit: 99707ef
Status: ✅  Deploy successful!
Preview URL: https://e35dd1d4.agoric-sdk.pages.dev
Branch Preview URL: https://pc-fusdc-advancer.agoric-sdk.pages.dev

View logs

@0xpatrickdev 0xpatrickdev force-pushed the pc/fusdc-status-manager branch 2 times, most recently from 444aedd to 88f51f3 Compare November 8, 2024 15:14
@0xpatrickdev 0xpatrickdev force-pushed the pc/fusdc-advancer branch 2 times, most recently from 725edd7 to 3483477 Compare November 8, 2024 20:47
@0xpatrickdev 0xpatrickdev force-pushed the pc/fusdc-status-manager branch from 88f51f3 to c1b9538 Compare November 8, 2024 23:55
@0xpatrickdev 0xpatrickdev force-pushed the pc/fusdc-status-manager branch 4 times, most recently from 8acd20c to a92b0ec Compare November 11, 2024 19:54
@0xpatrickdev 0xpatrickdev force-pushed the pc/fusdc-advancer branch 3 times, most recently from 229333d to 6f0bd04 Compare November 11, 2024 20:18
@0xpatrickdev 0xpatrickdev force-pushed the pc/fusdc-status-manager branch 2 times, most recently from 9eac623 to f3d1e36 Compare November 12, 2024 19:27
Base automatically changed from pc/fusdc-status-manager to master November 12, 2024 20:25
@0xpatrickdev 0xpatrickdev force-pushed the pc/fusdc-advancer branch 2 times, most recently from 37d455f to 1673c45 Compare November 13, 2024 21:31
import { assertAllDefined } from '@agoric/internal';
import { ChainAddressShape } from '@agoric/orchestration';
import { pickFacet } from '@agoric/vat-data';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

out of scope, but this helper should move eventually. It's about Exos, not vat data.

We could move it down to @agoric/internal but that is meant to not be consumed externally and this is valuable to other contract authors.

I wonder if it belongs in Endo.

*/

/** type guards internal to the AdvancerKit */
const WatcherHandlersShape = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shape is for objects that get passed around. This is an interface guard. It's a kit interface guard but you could still call it AdvancerI.

Why is this defined here and then composed with advancer in the Exo interface param?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was getting cute and trying to obscure the Vow handlers from the actual external interface. Changed to AdvancerI

* @param {LogFn} caps.log
* @param {StatusManager} caps.statusManager
* @param {VowTools} caps.vowTools
* @param {AdvancerKitCaps} caps
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this name makes sense. Elsewhere we've called it io. I don't think the style guide takes a position

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

powers is used similarly. Sometimes tools, though those are usually more closely related.

caps is not a dictionary word (or rather: it is, but it means "things you put on your head"). For very local usage, that doesn't matter much, but AdvancerKitCaps looks like something that might have a wider scope. Maybe AdvancerKitPowers instead?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh yeah, Powers. I think powers is strictly better than caps

}
advancer: {
/**
* Returns a Promise for a Vow in the happy path, or undefined
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please put this in @returns

packages/fast-usdc/src/exos/advancer.js Show resolved Hide resolved
try {
// should LiquidityPool return a vow here?
const { USDC: advancePmtP } =
await assetManagerFacet.borrowUnderlying(requestedAmount);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's underlying? did you mean underwriting?

Copy link
Member Author

@0xpatrickdev 0xpatrickdev Nov 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Underlying assets of the pool, not to be confused with shares, the other asset it owns. We can probably simplify to borrow() and return()repay()

destination,
amount: requestedAmount.value,
});
// do we actually need to await here?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deposit takes a payment so yes, unless borrowUnderlying returns a payment instead of a paymentP

const depositV = E(poolAccount).deposit(advancePmt);
return watch(depositV, this.facets.depositHandler, destination);
} catch (e) {
// TODO how should we think about failure here?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the deposit is unlikely to fail but the borrow could if the balance changes since it was looked up. Even though we're using a ZCFSeat we should design for if this were an ICA.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I've put a TODO for borrow failing. I think we can flesh that out more when we integrate the with the LiquidityPool.

For .deposit() failing, we can catch this separately in onRejected() and attempt to return the payment. The LP might need an interface for this, or return() will need to be trained to handle this scenario (right now, it's expected fees + principal).

packages/fast-usdc/src/fast-usdc.contract.js Show resolved Hide resolved
packages/orchestration/src/cosmos-api.ts Show resolved Hide resolved
@0xpatrickdev 0xpatrickdev marked this pull request as ready for review November 15, 2024 16:34
@0xpatrickdev 0xpatrickdev requested a review from a team as a code owner November 15, 2024 16:34
Copy link
Member

@turadg turadg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some small requests. I wouldn't object to them coming in a later PR.

I didn't carefully review error handling because we have that scheduled and it's probably best to tackle that holistically.

*/

/**
* Expected interface from LiquidityPool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll assume this @dckc agrees

* chainHub: ChainHub;
* log: LogFn;
* statusManager: StatusManager;
* USDC: { brand: Brand<'nat'>; denom: Denom; };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

non-blocking: I think we should refer to this as usdc in code. Treat "USDC" as a word and capitalize accordingly. Fully capitalized initialisms are to convey that each letter represents another word (United States Dollar Coin) but that's not relevant to the contract.

* localDenom: Denom;
* poolAccount: HostInterface<OrchestrationAccount<{ chainId: 'agoric' }>>;
* assetManagerFacet: AssetManagerFacet;
* poolAccount: ERef<HostInterface<OrchestrationAccount<{chainId: 'agoric';}>>>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: ; unnecessary and a little distracting

localDenom: M.string(),
poolAccount: M.remotable(),
assetManagerFacet: M.remotable(),
poolAccount: M.or(VowShape, M.remotable()),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO pick one

Copy link
Member Author

@0xpatrickdev 0xpatrickdev Nov 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like it'll depend on:

  • how we create the LCA (I believe zone.makeOnce() will return a Vow)
  • what incarnation we're in (first time it's a Vow, subsequently, a Remotable)

@@ -37,3 +37,8 @@ export const PendingTxShape = {
status: M.or(...Object.values(PendingTxStatus)),
};
harden(PendingTxShape);

export const QueryParamsShape = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is too generic and is easily confused with QueryParamsShape in address.js

consider EudParamShape


/**
* Default pattern matcher for `getQueryParams`.
* Does not assert keys exist, but ensures existing keys are strings.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is already guaranteed by your parser, but it doesn't hurt

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree for the getQueryParams fn, but {} seems to satisfy M.splitRecord({}, {}, M.recordOf(M.string(), M.string()))

@0xpatrickdev 0xpatrickdev added the automerge:rebase Automatically rebase updates, then merge label Nov 15, 2024
@mergify mergify bot merged commit 40ad937 into master Nov 15, 2024
91 checks passed
@mergify mergify bot deleted the pc/fusdc-advancer branch November 15, 2024 18:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
automerge:rebase Automatically rebase updates, then merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants