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

chore: fusdc multichain support #10626

Merged
merged 8 commits into from
Dec 6, 2024
Merged

chore: fusdc multichain support #10626

merged 8 commits into from
Dec 6, 2024

Conversation

0xpatrickdev
Copy link
Member

@0xpatrickdev 0xpatrickdev commented Dec 4, 2024

refs: #10597

Description

Primary changes:

  • @agoric/orchestration: exposes intermediateRecipient: ChainAddress['value'] in ForwardOpts, part of IBCMsgTransferOpts, allowing callers to provide their own value. Currently defaults to "pfm"
  • @agoric/fast-usdc: creates a Noble ICA in the StartFn so we have an address value for intermediateRecipient. Noble's chain does not permit non-bech32 values.

Ancillary:

  • @agoric/boot's bridgeUtils helpers:
    • setAckBehavior helper to control whether a IBCDowncallMethod acknowledgments are queued or inbounded immediately
    • setBech32Prefix helper to control address prefix for ICA accounts
    • ICA addresses are unique per account
  • @agoric/fast-usdc: remove blockTimestamp from CctpTxEvidence

Security Considerations

No new considerations

Scaling Considerations

None

Documentation Considerations

None

Testing Considerations

Updated existing tests.

Upgrade Considerations

N/A, library code part of FUSDC or NPM Orch release

Comment on lines -128 to -129
const stakingDenom = remoteChainInfo.stakingTokens?.[0]?.denom;
if (!stakingDenom) throw Fail`chain info lacks staking denom`;
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 can't recall why this was a check. It doesn't seem we rely on stakingDenom (anymore?)

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

IIRC having a stakingDenom was a proxy for some other guarantee about the chain, but I don't remember what that is and it seems like it's not necessary (if it ever was) because the other tests are passing.

Copy link
Member Author

@0xpatrickdev 0xpatrickdev Dec 4, 2024

Choose a reason for hiding this comment

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

I think I'm now remembering it was a proxy for which chains can make an ica / have staking actions.

It reminds me to create a ticket for CosmosChainInfo['icaEnabled'] (this is true for all current chains in KnownChains). This is where we'd perform the check. Edit: #10629

For something like delegate: never, we can continue rely on the CosmosChainAccountMethods type that looks for stakingTokens.

Copy link
Member

Choose a reason for hiding this comment

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

It seems to date back to...

I used git log --reverse -S'chain info lacks staking denom' -- src/exos/remote-chain-facade.js to find the 1st version it appeared in.

Copy link

cloudflare-workers-and-pages bot commented Dec 4, 2024

Deploying agoric-sdk with  Cloudflare Pages  Cloudflare Pages

Latest commit: 1847618
Status: ✅  Deploy successful!
Preview URL: https://94aac3dd.agoric-sdk.pages.dev
Branch Preview URL: https://pc-fusdc-multichain-support.agoric-sdk.pages.dev

View logs

@0xpatrickdev 0xpatrickdev marked this pull request as ready for review December 4, 2024 22:35
@0xpatrickdev 0xpatrickdev requested a review from a team as a code owner December 4, 2024 22:35
Copy link
Member

Choose a reason for hiding this comment

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

replying to the commit message… maybe the flags tooling in agd-tools should be more flexible?

also, typo 'arugment'

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 gave this a shot and came up short. Would welcome someone else picking it up.

Relatedly - excited/hopeful to start using @agoric/client-utils in multichain-testing.

@@ -334,6 +334,8 @@ export interface IBCMsgTransferOptions {
timeoutTimestamp?: MsgTransfer['timeoutTimestamp'];
memo?: string;
forwardOpts?: {
/** The recipient address for the intermediate transfer. Defaults to 'pfm' unless specified */
Copy link
Member

Choose a reason for hiding this comment

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

nice forward and backward compatible solution

Comment on lines -128 to -129
const stakingDenom = remoteChainInfo.stakingTokens?.[0]?.denom;
if (!stakingDenom) throw Fail`chain info lacks staking denom`;
Copy link
Member

Choose a reason for hiding this comment

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

IIRC having a stakingDenom was a proxy for some other guarantee about the chain, but I don't remember what that is and it seems like it's not necessary (if it ever was) because the other tests are passing.

packages/boot/tools/supports.ts Show resolved Hide resolved
Copy link
Member

@dckc dckc left a comment

Choose a reason for hiding this comment

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

I need to understand better what intermediateRecipient is used for.

None of the rest of the comments are important/critical.

@@ -236,7 +237,7 @@ export default async (homeP, endowments) => {
// @ts-expect-error ensured by options
const {
values: {
oracle: oracleArgs,
oracles: oracleArgs,
Copy link
Member

Choose a reason for hiding this comment

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

the oracleArgs alias no longer seems appropriate; it's a single arg now.

Comment on lines 177 to 178
const oraclesUsage = 'use --oracle name:address ...';
const oraclesUsage = 'use --oracles "["name:address","name:address"]"';
Copy link
Member

Choose a reason for hiding this comment

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

This seems like a UX regression, and the motivation seems to be an internal testing API. Seems like the tail wagging the dog. But oh well. The script has a limited userbase too.

Meanwhile, if we're using JSON on the command line, why not get rid of the name:address syntax while we're at it? How about --oracles '{"name":"address", ...}'.

Copy link
Member Author

Choose a reason for hiding this comment

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

Removed this commit from the PR

@@ -266,7 +267,7 @@ export default async (homeP, endowments) => {
}
if (!oracleArgs) throw Error(oraclesUsage);
return Object.fromEntries(
oracleArgs.map(arg => {
JSON.parse(oracleArgs).map(arg => {
Copy link
Member

Choose a reason for hiding this comment

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

as noted above if we're using JSON.parse, we might as well get rid of the regex and Object.fromEntries.

@@ -116,6 +116,7 @@ export const prepareAdvancerKit = (
* notifyFacet: import('./settler.js').SettlerKit['notify'];
* borrowerFacet: LiquidityPoolKit['borrower'];
* poolAccount: HostInterface<OrchestrationAccount<{chainId: 'agoric'}>>;
* intermediateRecipient: ChainAddress;
Copy link
Member

Choose a reason for hiding this comment

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

we seem to throw away all but the .value without checking it. Just use a string?

Copy link
Member

Choose a reason for hiding this comment

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

better to check it, but even without checking it there's utility in knowing it's not just a string but a ChainAddress

/** @type {HostInterface<OrchestrationAccount<{chainId: 'agoric';}>>[]} */
const [poolAccount, settlementAccount] = await vowTools.when(
vowTools.all([poolAccountV, settleAccountV]),
/** @type {[HostInterface<OrchestrationAccount<{chainId: 'noble-1';}>>, HostInterface<OrchestrationAccount<{chainId: 'agoric';}>>, 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.

chainId is noble-1 but not agoric-3?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is some tech debt that would hopefully be solved in #9992. agoric is a special case in the types currently since checks do ~startsWith (to support agoriclocal and agoric-3).

Agree this is confusing, updated to use agoric-3 here.

@@ -280,6 +285,11 @@ test('slow path: forward to EUD; remove pending tx', async t => {
value: 'osmo183dejcnmkka5dzcu9xw6mywq0p2m5peks28men',
},
usdc.units(150),
{
forwardOpts: {
intermediateRecipient: 'noble1test',
Copy link
Member

Choose a reason for hiding this comment

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

Using the same property name for a string here and a ChainAddress elsewhere is hurting my tiny brain.

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, in hindsight this was a poor decision. Updated everything to use the ChainAddress object.

@@ -690,6 +690,7 @@ export const prepareLocalOrchestrationAccountKit = (
'agoric',
forwardOpts,
);
trace('got transfer route', q(route).toString());
Copy link
Member

Choose a reason for hiding this comment

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

using .toString() with q(...) looks odd somehow. hm.

Comment on lines -128 to -129
const stakingDenom = remoteChainInfo.stakingTokens?.[0]?.denom;
if (!stakingDenom) throw Fail`chain info lacks staking denom`;
Copy link
Member

Choose a reason for hiding this comment

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

It seems to date back to...

I used git log --reverse -S'chain info lacks staking denom' -- src/exos/remote-chain-facade.js to find the 1st version it appeared in.

@@ -245,6 +245,7 @@ export const ForwardOptsShape = M.splitRecord(
{
timeout: M.string(),
retries: M.number(),
intermediateRecipient: M.string(),
Copy link
Member

Choose a reason for hiding this comment

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

again, my brain goes: not ChainAddressShape?
I can see that it's correct, but using the same name for 2 things is hurting my brain.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed

trace('poolAccount', poolAccount);
trace('nobleAccount', nobleAccount);

const intermediateRecipient = await vowTools.when(
Copy link
Member

Choose a reason for hiding this comment

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

This address... it's not used for anything other than bech32 checksum validation, right?

How about using bech32.encode('agoric', Array(20).fill(0)) aka agoric1qqqqqqqqqqqqqqqqqqqqhlgkpj?

Copy link
Member

Choose a reason for hiding this comment

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

This address... it's not used for anything other than bech32 checksum validation, right?

My answer to "How about using... ?" completely depends on the answer to the above (which I suspect is used for something other than checksum validation). I don't know the answer to the above.

@0xpatrickdev 0xpatrickdev force-pushed the pc/fusdc-multichain-support branch from d58d038 to 2614509 Compare December 5, 2024 00:31
- for some chains, "pfm" is not a valid `recipient` for PFM transfers
- this change allows callers to provide a value
@0xpatrickdev 0xpatrickdev force-pushed the pc/fusdc-multichain-support branch from 2614509 to 75ce4a9 Compare December 5, 2024 17:11
@0xpatrickdev 0xpatrickdev force-pushed the pc/fusdc-multichain-support branch 2 times, most recently from 42ac99a to be4b63b Compare December 5, 2024 20:41
@0xpatrickdev 0xpatrickdev requested review from dckc and turadg December 5, 2024 20:52
/** inbound messages are delivered immediately */
Immediate: 'IMMEDIATE',
} as const;
type AckBehaviorType = (typeof AckBehavior)[keyof typeof AckBehavior];
Copy link
Member

Choose a reason for hiding this comment

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

We have a way to make the type name be the same as the value name in JSDoc. In .ts one would usually do enum. I'm not sure how to do it in .ts without enum.

Comment on lines 512 to 514
shouldAckImmediately(bridgeId, 'startChannelOpenInit')
? inbound(BridgeId.DIBC, message)
: pushInbound(BridgeId.DIBC, message);
Copy link
Member

Choose a reason for hiding this comment

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

ternaries are for expressions, not control flow.

Suggested change
shouldAckImmediately(bridgeId, 'startChannelOpenInit')
? inbound(BridgeId.DIBC, message)
: pushInbound(BridgeId.DIBC, message);
const handle = shouldAckImmediately(bridgeId, 'startChannelOpenInit') ? inbound : pushInbound;
handle(BridgeId.DIBC, message);

- adds helper method that allows callers to change the way certain bridges, like DIBC, handle acknowledgements
- defaults to QUEUED, where callers need to explicity use `flushInboundQueue`. adds the ability to set to IMMEDIATE,
  where bridge messages are immediately acknowledged on receipt
- noble only accepts bech32 addresses for the recipient field in ibc transfers
- this change creates an ICA noble to facilitate the requirement
- if an IBC transfer fails, we expect it to return the origin (agoric `localOrchAccount`), not the `intermediateRecipient`
- adds ability to use something besides "cosmos" for mock ICA address prefix
@0xpatrickdev 0xpatrickdev force-pushed the pc/fusdc-multichain-support branch from be4b63b to 1847618 Compare December 5, 2024 23:20
@0xpatrickdev 0xpatrickdev added the automerge:rebase Automatically rebase updates, then merge label Dec 5, 2024
Copy link
Contributor

mergify bot commented Dec 6, 2024

This pull request has been removed from the queue for the following reason: checks failed.

The merge conditions cannot be satisfied due to failing checks:

You should look at the reason for the failure and decide if the pull request needs to be fixed or if you want to requeue it.

If you want to requeue this pull request, you need to post a comment with the text: @mergifyio requeue

@0xpatrickdev
Copy link
Member Author

@mergify requeue

Copy link
Contributor

mergify bot commented Dec 6, 2024

requeue

☑️ This pull request is already queued

@mergify mergify bot merged commit ef9088c into master Dec 6, 2024
91 checks passed
@mergify mergify bot deleted the pc/fusdc-multichain-support branch December 6, 2024 00:54
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.

4 participants