-
Notifications
You must be signed in to change notification settings - Fork 233
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
docs: add initial threat model diagrams for multipool autoswap and treasury #3888
Changes from all commits
f8c675a
edf8b14
1c37852
2844238
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#!/bin/sh | ||
pumljar="${PLANTUML:-$HOME/plantuml/plantuml.jar}" | ||
page="index.md" | ||
java -jar "$pumljar" "./**/*.puml" | ||
echo "# Threat Model Diagrams" > "$page" | ||
for diag in $(find . -name "*.png" | sort); do | ||
echo "## $diag\n" >> "$page" | ||
echo "[]($diag)\n" >> "$page" | ||
done |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Threat Model Diagrams | ||
## ./smart_contracts/multipool_autoswap/mpas_component.png | ||
|
||
[](./smart_contracts/multipool_autoswap/mpas_component.png) | ||
|
||
## ./smart_contracts/multipool_autoswap/mpas_sequence.png | ||
|
||
[](./smart_contracts/multipool_autoswap/mpas_sequence.png) | ||
|
||
## ./smart_contracts/multipool_autoswap/mpas_sequence_001.png | ||
|
||
[](./smart_contracts/multipool_autoswap/mpas_sequence_001.png) | ||
|
||
## ./smart_contracts/multipool_autoswap/mpas_sequence_002.png | ||
|
||
[](./smart_contracts/multipool_autoswap/mpas_sequence_002.png) | ||
|
||
## ./smart_contracts/multipool_autoswap/mpas_sequence_003.png | ||
|
||
[](./smart_contracts/multipool_autoswap/mpas_sequence_003.png) | ||
|
||
## ./treasury/treasury.png | ||
|
||
[](./treasury/treasury.png) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
@startuml | ||
'https://plantuml.com/component-diagram | ||
header Agoric Systems Operating Company. | ||
footer v0.0.1 | ||
title Multiswap Auto Pool Component Diagram | ||
|
||
skinparam componentStyle rectangle | ||
skinparam defaultTextAlignment center | ||
|
||
actor "Multipool Autoswap Contract creator" as cc1 | ||
actor "Random Pool Creator" as cc2 | ||
actor "Person wanting to swap" as cc3 | ||
interface "startInstance()" as si0 | ||
package "zoe" as zoe { | ||
interface "offer()" as offer | ||
} | ||
|
||
package "Multipool Autoswap" { | ||
[creatorFacet] as cf0 | ||
node contractFacet <<zcf>> as conf1 { | ||
package "poolSeatA" as pa1 { | ||
interface "incrementBy" as pa1i1 | ||
interface "decrementBy" as pa1i2 | ||
} | ||
|
||
package "poolSeatB" as pa2 { | ||
interface "incrementBy" as pa2i1 | ||
interface "decrementBy" as pa2i2 | ||
} | ||
package "UserSeat" as use { | ||
interface "incrementBy" as usi1 | ||
interface "decrementBy" as usi2 | ||
} | ||
|
||
interface "reallocate" as reall | ||
|
||
} | ||
package "publicFacet" as pf0 { | ||
interface "addPool()" as ap | ||
interface "otherMethods..." as om | ||
} | ||
|
||
si0 -> cf0 | ||
|
||
|
||
node "Pool B" as poolb { | ||
[Central Token] as ct2 | ||
database "Price Registry" <<Central/B>> as pr2 | ||
[Secondary Token B] | ||
[Secondary Token B] --> ct2 | ||
interface "getPoolSeat()" as gps2 | ||
} | ||
|
||
node "Pool A" as poola { | ||
[Central Token] as ct1 | ||
database "Price Registry" <<Central/A>> as pr1 | ||
[Secondary Token A] | ||
[Secondary Token A] --> ct1 | ||
interface "getPoolSeat()" as gps1 | ||
} | ||
|
||
node "pool n" as pooln { | ||
} | ||
|
||
ap -d-> pooln | ||
|
||
offer --> conf1: execute method | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is this part of the diagram ( Everything else appears to be either the ways a client of the APIs can interact with methods on the AMM pools or how zoe/zcf manage the balances of the pools. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In regards to Zoe, I wanted to show that it referenced the contract and in invoked the contract functionality, however I may have it backwards. What is the best way to represent There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here's a quick sketch. Zoe holds funds in escrow, and has the user seats. each user seat is paired with a ZCF seat in the corresponding ZCF vat. A ZCF vat runs a single contract (in this case MPAS). MPAS has multiple pools, each of which knows two balances that reflect a claim on escrowed funds in Zoe. When a seat is created for a transaction ( The publicFacet, creatorFacet, etc. could also be pictured within the ZCF vat, since they're facets of the contract. We can jump on a call if you want to wave my hands and point at the parts of the diagram. |
||
|
||
gps1 -d-> pa1 | ||
gps2 -d-> pa2 | ||
conf1 --> pa1i1 | ||
conf1 --> pa1i2 | ||
conf1 --> pa2i1 | ||
conf1 --> pa2i2 | ||
conf1 --> usi1 | ||
conf1 --> usi2 | ||
conf1 --> reall | ||
} | ||
|
||
cc1 --> si0 | ||
cc2 --> ap | ||
cc3 -u-> offer | ||
offer -> offer: validate terms | ||
|
||
offer -> use | ||
cc3 --r-> use: reclaim funds | ||
cc3 --> om | ||
@enduml |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
@startuml | ||
'https://plantuml.com/sequence-diagram | ||
header Agoric Systems Operating Company. | ||
footer Page %page% of %lastpage% | ||
title Multipool Auto Swap Sequence Diagram Creation | ||
|
||
autonumber | ||
actor "MPAS Creator" as masc #lime | ||
actor "Pool Adder N" as pa #yellow | ||
actor "Pool User" as pu | ||
database "MPAS Contract" as mpas | ||
box "Zoe" | ||
entity "Zoe" as zoe | ||
entity "userSeat" as usA | ||
end box | ||
|
||
== MPAS Creation == | ||
masc -> mpas: Create instance | ||
return ""creatorFacet"" | ||
== Pool Addition SML:BCK== | ||
autonumber 10 | ||
pa -> mpas: ""addPool()"" | ||
Comment on lines
+19
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In order to get from creating an instance to adding a pool, the creator has to publish the instance of the contract somewhere. Otherwise, even though the addPool() method is "public", no one would be able to find it. It is completely possible in this model to create an AMM, and add pools, and only tell friends about it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it possible to enumerate or directly reference this contract somehow through reflection or other means? Or does it need to be explicitly published? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It needs to be explicitly published. We have a Board on which references to such things can be shared, but it takes an explicit action to make them visible. It's a crucial part of the security model. We don't want to treat instances of contracts like they're ambient authority, even though we do share them widely for convenience in some circumstances. |
||
database "Pool SML:BUCK" as pool | ||
entity "poolSeat SML:BUCK" as psA | ||
|
||
mpas -> pool: Create pool for SML -> BUCK | ||
mpas --> pa: ""Issuer"" | ||
== Pool Addition MOOL:BCK== | ||
autonumber 10 | ||
pa -> mpas: ""addPool()"" | ||
database "Pool MOOL:BUCK" as pool2 | ||
mpas -> pool2: Create pool for MOOL -> BUCK | ||
mpas --> pa: ""Issuer"" | ||
|
||
|
||
== Duplicate Pool Addition MOOL:BCK== | ||
autonumber 30 | ||
pa -> mpas: ""addPool()"" | ||
mpas -->x pa: pool for MOOL:BCK already exists | ||
newpage Multipool Auto Swap Sequence Diagram Swap Request | ||
|
||
autonumber 50 | ||
== Swap Request == | ||
group asking for the current price UNK:BUCK | ||
pu -> mpas: ""getOutputPrice(UNK:BUCK)"" | ||
mpas -->x pu: ""brands were not recognized"" | ||
end | ||
group asking for the current price MOOL:BUCK | ||
|
||
|
||
pu -> mpas: ""getOutputPrice(MOOL:BUCK)"" | ||
mpas -> pool2: ""getPriceGivenRequiredOutput(MOOL:BUCK)"" | ||
pool2 --> mpas: ""quote"" | ||
mpas --> pu: ""quote"" | ||
end | ||
|
||
group making a proposal | ||
pu -> pu: create proposal for SML:BUCK as ""proposal"" | ||
|
||
end | ||
|
||
group requesting an invitation for a SwapOut | ||
pu -> mpas: ""makeSwapOutInvitation()"" | ||
return ""invitation"" | ||
|
||
end | ||
|
||
group making an offer | ||
pu -> pu: withdraw funds from purse of SML into ""payment"" | ||
pu -> zoe: ""offer(invitation, proposal, payment))"" | ||
zoe -> zoe: validate offer | ||
|
||
zoe -> usA: create ""userSeat"" | ||
usA --> zoe: ""userSeat"" | ||
zoe -> pool: ""getPoolSeat()"" | ||
pool -> psA: create ""poolSeat"" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's no "Create poolSeat" call at this point in the transaction. I would actually show the poolSeat as having the same lifetime as the Pool. It's created when the pool comes into existence, and holds the pools assets. |
||
psA --> zoe: ""poolSeat"" | ||
mpas -> psA: stage assets | ||
mpas -> usA: stage assets | ||
zoe -> zoe: ""reallocate(seat, poolSeat)"" | ||
|
||
usA --> pu: ""userSeat"" | ||
pu -> zoe: ""getOfferResult()"" | ||
return result of failure or success | ||
end | ||
group recovering funds | ||
jessysaurusrex marked this conversation as resolved.
Show resolved
Hide resolved
|
||
pu -> usA: ""getPayout("Central")"" (give) | ||
return ""payoutCentral"" | ||
pu -> pu: deposit ""payoutCentral"" into purse | ||
pu -> usA: ""getPayout("Secondary")"" (want) | ||
return ""payoutSecondary"" | ||
pu -> pu: deposit ""payoutSecondary"" into purse | ||
end | ||
|
||
newpage Multipool Auto Swap Sequence Diagram Adding Liquidity | ||
|
||
autonumber 100 | ||
== Adding Liquidity == | ||
group discover existing proportion of balances | ||
pu -> pool: ""getPoolAllocation(SML)"" | ||
return ""poolAllocation"" | ||
end | ||
group create invite | ||
pu -> mpas: ""makeAddLiquidityInvitation"" | ||
return ""invitation"" | ||
end | ||
|
||
|
||
group create proposal | ||
pu -> pu: Create ""proposal"" to add 1 BUCK, and 1 SML\nat ratio of ""poolAllocation"" for X ""liquidity"" | ||
end | ||
group withdraw funds | ||
pu -> pu: withdraw funds for ""BUCK"" into ""payments"" record | ||
pu -> pu: withdraw funds for ""SML"" into ""payments"" record | ||
pu -> zoe: ""offer(invitation, proposal, payments)"" | ||
zoe -> zoe: validate offer | ||
|
||
zoe -> usA: create ""userSeat"" | ||
usA --> zoe: ""userSeat"" | ||
zoe -> pool: ""getPoolSeat()"" | ||
pool -> psA: create ""poolSeat"" | ||
psA --> zoe: ""poolSeat"" | ||
|
||
zoe -> psA: ""addLiquidity"" | ||
mpas -> psA: stage assets | ||
mpas -> usA: stage assets | ||
zoe -> zoe: ""reallocate(seat, poolSeat)"" | ||
|
||
usA --> pu: ""userSeat"" | ||
pu -> zoe: ""getOfferResult()"" | ||
return result of failure or success | ||
end | ||
group recovering funds | ||
pu -> usA: ""getPayout("Central")"" (give) | ||
return ""payoutCentral"" | ||
pu -> pu: deposit ""payoutCentral"" into purse | ||
pu -> usA: ""getPayout("Secondary")"" (give) | ||
return ""payoutSecondary"" | ||
pu -> pu: deposit ""payoutSecondary"" into purse | ||
pu -> usA: ""getPayout("Liquidity")"" (want) | ||
return ""payoutLiquidity"" | ||
pu -> pu: deposit ""payoutLiquidity"" into purse | ||
end | ||
|
||
|
||
newpage Multipool Auto Swap Sequence Diagram Removing Liquidity | ||
|
||
autonumber 200 | ||
== Removing Liquidity == | ||
group discover existing proportion of balances | ||
pu -> pool: ""getPoolAllocation(SML)"" | ||
return ""poolAllocation"" | ||
end | ||
group create invite | ||
pu -> mpas: ""makeAddLiquidityInvitation"" | ||
return ""invitation"" | ||
end | ||
|
||
|
||
group create proposal | ||
pu -> pu: Create ""proposal"" to remove 1 ""liquidity"" for 1 BUCK and 1 SML\nat ratio of ""poolAllocation"" | ||
end | ||
group withdraw funds | ||
pu -> pu: withdraw funds for ""liquidity"" into ""payments"" record | ||
pu -> zoe: ""offer(invitation, proposal, payments)"" | ||
zoe -> zoe: validate offer | ||
|
||
zoe -> usA: create ""userSeat"" | ||
usA --> zoe: ""userSeat"" | ||
zoe -> pool: ""getPoolSeat()"" | ||
pool -> psA: create ""poolSeat"" | ||
psA --> zoe: ""poolSeat"" | ||
|
||
zoe -> psA: ""addLiquidity"" | ||
mpas -> psA: stage assets | ||
mpas -> usA: stage assets | ||
zoe -> zoe: ""reallocate(seat, poolSeat)"" | ||
|
||
usA --> pu: ""userSeat"" | ||
pu -> zoe: ""getOfferResult()"" | ||
return result of failure or success | ||
end | ||
group recovering funds | ||
pu -> usA: ""getPayout("Liquidity")"" (give) | ||
return ""payoutLiquidity"" | ||
pu -> pu: deposit ""payoutLiquidity"" into purse | ||
pu -> usA: ""getPayout("Central")"" (want) | ||
return ""payoutCentral"" | ||
pu -> pu: deposit ""payoutCentral"" into purse | ||
pu -> usA: ""getPayout("Secondary")"" (want) | ||
return ""payoutSecondary"" | ||
pu -> pu: deposit ""payoutSecondary"" into purse | ||
end | ||
|
||
@enduml |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
@startuml | ||
header Agoric Systems Operating Company. | ||
footer v0.0.1 | ||
title Treasury | ||
|
||
skinparam componentStyle rectangle | ||
skinparam defaultTextAlignment center | ||
|
||
|
||
actor "TreasuryCreator aka Governance" as tc | ||
|
||
actor Borrower | ||
|
||
node AdjustBalancesInvitation | ||
node "CloseVaultInvitation" | ||
node LiquidationPromise | ||
node LiquidationSeat { | ||
circle getPayout | ||
circle getPayouts | ||
} | ||
node "Vat" { | ||
jessysaurusrex marked this conversation as resolved.
Show resolved
Hide resolved
|
||
node Treasury { | ||
node AMM | ||
node "publicAPI" { | ||
circle getCollaterals | ||
circle makeLoanInvitation | ||
circle getRunIssuer | ||
circle getAMM | ||
getAMM -d-> AMM | ||
} | ||
node "creatorFacet" { | ||
circle makeAddTypeInvitation | ||
} | ||
} | ||
node "Vault" { | ||
circle makeCloseInvitation | ||
makeCloseInvitation -u-> CloseVaultInvitation | ||
circle makeAdjustBalancesInvitation | ||
makeAdjustBalancesInvitation -u-> AdjustBalancesInvitation | ||
circle getCollateralAmount | ||
circle getDebtAmount | ||
circle getLiquidationSeat | ||
getLiquidationSeat -u-> LiquidationSeat | ||
circle getLiquidationPromise | ||
getLiquidationPromise -u-> LiquidationPromise | ||
} | ||
} | ||
Borrower -> makeLoanInvitation: open vault and transfer collateral | ||
makeLoanInvitation -d-> Vault | ||
Borrower -u-> getPayout: retrieve any proceeds | ||
Borrower -u-> getPayouts: retrieve any proceeds | ||
Borrower -d-> LiquidationPromise: did loan get liquidated? | ||
Borrower -> AdjustBalancesInvitation: add or remove collateral or \nincrease or decrease the loan balance | ||
Borrower -l-> CloseVaultInvitation: close loan and withdraw \nany remaining collateral | ||
tc -d-> makeAddTypeInvitation | ||
Borrower -d-> getDebtAmount: how much do I owe | ||
Borrower -d-> getCollateralAmount: how much did I \ndeposit as collateral | ||
|
||
@enduml |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, useful! I'm going to have to crib from this for the governance diagrams.