On-chain registry for MIP-21 contracts for Real World Assets (RWA).
The RWA Registry aims to be flexible and extensible registry for all current and future components of the MIP-21 architecture, without requiring features such as upgradeability and facets, which bring more complexity.
To prevent malicious updates, all non-view methods are permissioned.
RWA deals are identified by their collateral type (ilk
). RWA ilk
s come in the form of RWA123-A
, where 123
is a
sequential number.
Each RWA deal consists of:
status
: the status of the deal. Non-existent deals have aNONE
status. It is set toACTIVE
once the deal is added to the registry and toFINALIZED
once the deal is finished.┌──────┐ add() ┌────────┐ finalize() ┌───────────┐ │ NONE ├──────────────► ACTIVE ├──────────────► FINALIZED │ └──────┘ └────────┘ └───────────┘
components
: the list of components of a deal.
The contract maintains an append-only list of supported components, identified by their camelCased
names.
addSupportedComponent(bytes32 componentName_): void
: adds a new supported component to the registry.listSupportedComponents(): bytes32[]
: returns the list of supported components.
Deal components consist of:
name: bytes32
: thecamelCased
name of the component. It has to be one of the supported components.addr: address
: the address of the component, be it a smart contract or an EOA.variant: uint8
*: we have identified early on that components fulfilling the same role may have different implementations. Following the same approach of theGemJoin
adapters, each implementation has a numeric suffix identifying it. This allows consumers to know precisely with which implementation they are dealing with when querying the registry. Different components can have different reserved values for variants with special meaning and should be documented below.
* Variant is only stored as uint8
, but when used as calldata
(parameters of or returning from functions)
they are upcast to uint256
. See this
article for further reference.
The RWA vault.
Variants:
# | Description |
---|---|
1 |
The base implementation of a permissioned vault. See RwaUrn.sol . |
2 |
A permissioned vault based on #1 , allowing to claim deposited Dai without Emergency Shutdown. See RwaUrn2.sol . |
The RWA liquidation oracle, controlled by MakerDAO governance to put RWA vaults in liquidation when the conditions on the deal are not met.
Variants:
# | Description |
---|---|
1 |
The base implementation the of liquidation oracle. See RwaLiquidationOracle.sol |
The RWA output conduit, acts as a temporary holder for Dai when it is generated from a vault.
Variants:
# | Description |
---|---|
1 |
The base implementation the output conduit. See RwaOutputConduit.sol |
2 |
Based on #1 , with a permissioned push() method. See RwaOutputConduit2.sol |
3 |
Designed to swap Dai into PSM gems on push() . See RwaSwapOutputConduit.sol |
type(uint8).max |
Not a real conduit. Should be used when Dai is drawn directly into the destination and be treated as an opaque address , not a smart contract. |
The RWA input conduit, acts as a temporary holder for Dai or other gems when it is deposited into a vault.
Variants:
# | Description |
---|---|
1 |
The base implementation the input conduit. See RwaInputConduit.sol |
2 |
Based on #1 , with a permissioned push() method. See RwaInputConduit2.sol |
3 |
Designed to receive PSM gems and swap them into a Dai on push() . See RwaSwapInputConduit.sol |
4 |
Designed to receive PSM gems and swap them into a Dai on push() , with a permissionless push() . See RwaSwapInputConduit2.sol |
The RWA container for stability fee payments directly into MakerDAO's Surplus Buffer.
Variants:
# | Description |
---|---|
1 |
The base implementation the jar. See RwaJar.sol |
The RWA Jar input conduit, acts as a temporary holder for Dai or other gems when it is deposited into the jar for stability fee payments.
The main use case for jarInputConduit
is when stability fees need to be paid using a PSM gem instead of Dai. The swap input conduit can be used for to swap the gem into Dai before moving it to the jar.
# | Description |
---|---|
3 |
Designed to receive PSM gems and swap them into a Dai on push() . See RwaSwapInputConduit.sol |
4 |
Designed to receive PSM gems and swap them into a Dai on push() , with a permissionless push() . See RwaSwapInputConduit2.sol |
// Add a deal without any components
registy.add('<ILK>');
// Add a deal with components
registy.add(
'<ILK>',
['liquidationOracle', 'urn', 'inputConduit', 'outputConduit'], // names
[0x1234..., 0x1235..., 0x1236..., 0x1236...], // addresses
[1, 1, 2, 2] // variants
);
registy.setCompoonent('<ILK>', 'liquidationOracle', 0x1234..., 1);
registy.listComponentsOf('<ILK>');
// Returns:
// ['liquidationOracle', 'urn', 'inputConduit', 'outputConduit'], // names
// [0x1234..., 0x1235..., 0x1236..., 0x1236...], // addresses
// [1, 1, 2, 2] // variants
registy.getCompoonent('<ILK>', 'liquidationOracle');
// Returns:
// 0x1234..., // address
// 1 // variant
registry.addSupportedComponent('newComponentName');
registry.listSupportedComponents();
// Returns:
// ['liquidationOracle', 'urn', 'inputConduit', 'outputConduit', 'jar', 'jarInputConduit', ...]
# Install tools from the nodejs ecosystem: prettier, solhint, husky and lint-staged
make nodejs-deps
# Install smart contract dependencies through `foundry update`
make update
cp .env.example .env
make build
make test # using a local node listening on http://localhost:8545
# Or
ETH_RPC_URL='https://eth-goerli.alchemyapi.io/v2/<ALCHEMY_API_KEY>' make test # using a remote node
Wrapper around forge
/cast
which figure out wallet and password automatically if you are using geth
keystore.
scripts/forge-deploy.sh
: Deploys a contract. Accepts the same options asforge create
scripts/forge-verify.sh
: Verifies a deployed contract. Accepts the same options asforge verify-contract
scripts/cast-send.sh
: Signs and publish a transaction. Accepts the same options ascast send