# Notional V3

## Architecture

Main Notional V3 interactions are called through the Notional Proxy which are routed to various implementation contracts. Wrapped fCash and nToken ERC20 transfers are exceptions, those methods are called via their own external proxies.

<figure><img src="https://2383526294-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FSxpEAtY7TM4KhLALu6db%2Fuploads%2FnZLChyFoROFbkLhTpbos%2Fimage.png?alt=media&amp;token=d87300d7-65fe-4bf7-bf8b-393d58bb67fd" alt=""><figcaption></figcaption></figure>

## Technical Walkthrough Video

Here is a [link](https://www.youtube.com/watch?v=e6YbiQkHYrQ) to the Notional V3 Technical Walkthrough video.


# Ethereum Mainnet

## Deployed Contract Addresses

<table><thead><tr><th width="186">Contract</th><th>Address</th></tr></thead><tbody><tr><td>Notional Proxy</td><td><a href="https://etherscan.io/address/0x6e7058c91f85e0f6db4fc9da2ca41241f5e4263f">0x6e7058c91f85e0f6db4fc9da2ca41241f5e4263f</a></td></tr><tr><td>NOTE address</td><td><a href="https://etherscan.io/address/0xcfeaead4947f0705a14ec42ac3d44129e1ef3ed5">0xcfeaead4947f0705a14ec42ac3d44129e1ef3ed5</a></td></tr></tbody></table>

## nToken Addresses

<table><thead><tr><th width="214">Token</th><th>Address</th></tr></thead><tbody><tr><td>nETH</td><td><a href="https://etherscan.io/address/0x3410463726a7A22ce0809367a4418FE82Fc31FD3">0x3410463726a7A22ce0809367a4418FE82Fc31FD3</a></td></tr><tr><td>nDAI</td><td><a href="https://etherscan.io/address/0x87C478f00999d65F88D3088291a6928b55703444">0x87C478f00999d65F88D3088291a6928b55703444</a></td></tr><tr><td>nUSDC</td><td><a href="https://etherscan.io/address/0x2920F9Fc667E780C0CB5a78a104d21413377f97E">0x2920F9Fc667E780C0CB5a78a104d21413377f97E</a></td></tr><tr><td>nwstETH</td><td><a href="https://etherscan.io/address/0x9499ad68Cd1b00a869853a986ac3F82401650933">0x9499ad68Cd1b00a869853a986ac3F82401650933</a></td></tr><tr><td>nFRAX</td><td><a href="https://etherscan.io/address/0x96bE0C426Ea53ECb6F154bEd27c9dE85722A5C6F">0x96bE0C426Ea53ECb6F154bEd27c9dE85722A5C6F</a></td></tr><tr><td>nrETH</td><td><a href="https://etherscan.io/address/0xd623646DA89F9264547272f268785d9C64af9ce3">0xd623646DA89F9264547272f268785d9C64af9ce3</a></td></tr><tr><td>nUSDT</td><td><a href="https://etherscan.io/address/0x0da210f60a179ee3364123943930dadbab8b210e">0x0Da210F60A179Ee3364123943930dAdbAb8B210e</a></td></tr><tr><td>ncbETH</td><td><a href="https://etherscan.io/address/0xa2adbc0d7c8da646f9d5f6cfa9eb396403067da0">0xa2ADBc0d7C8Da646f9d5f6CfA9Eb396403067da0</a></td></tr><tr><td>nGHO</td><td><a href="https://etherscan.io/address/0x2f7350cb5e434c2d177922110c7e314953b84afc">0x2F7350Cb5e434C2d177922110c7e314953B84Afc</a></td></tr></tbody></table>

## pCash Addresses

<table><thead><tr><th width="214">Token</th><th>Address</th></tr></thead><tbody><tr><td>pETH</td><td><a href="https://etherscan.io/address/0x4a9e282635567cC4D3C6a24E16C2335f10Dee9B8">0x4a9e282635567cC4D3C6a24E16C2335f10Dee9B8</a></td></tr><tr><td>pDAI</td><td><a href="https://etherscan.io/address/0x54fa13a38a690bc69584a7ac8b834c1770959974">0x54fA13A38a690bC69584A7aC8b834c1770959974</a></td></tr><tr><td>pUSDC</td><td><a href="https://etherscan.io/address/0xaeeafb1259f01f363d09d7027ad80a9d442de762">0xaEeAfB1259f01f363d09D7027ad80a9d442de762</a></td></tr><tr><td>pWBTC</td><td><a href="https://etherscan.io/address/0x83706a2ec580fe1fdb84744366fa02fb8e25d29d">0x83706A2Ec580Fe1Fdb84744366FA02Fb8e25D29D</a></td></tr><tr><td>pwstETH</td><td><a href="https://etherscan.io/address/0xfbadc4f18ddc7ebdbc920d3f9b0ca7a1296788d1">0xfbAdc4f18dDC7EBdBc920d3f9b0Ca7A1296788d1</a></td></tr><tr><td>pFRAX</td><td><a href="https://etherscan.io/address/0x7ef4d0168b12b168f14b67c708bc16f7e8bf3dec">0x7Ef4d0168b12b168F14b67c708bc16f7E8BF3dEC</a></td></tr><tr><td>prETH</td><td><a href="https://etherscan.io/address/0x39a1f8e5d2422ccc5e08c5b4019ab70147f5cc95">0x39A1f8e5D2422CCc5e08c5B4019Ab70147f5cC95</a></td></tr><tr><td>pUSDT</td><td><a href="https://etherscan.io/address/0x4ebfc11ad2dd1c2a450ba194558d797ee5d305a6">0x4ebFc11Ad2Dd1c2A450ba194558D797ee5D305a6</a></td></tr><tr><td>pcbETH</td><td><a href="https://etherscan.io/address/0x265329c8f15671d7ca501710e3bd0e6cb257948f">0x265329C8F15671d7cA501710e3bD0E6CB257948F</a></td></tr><tr><td>psDAI</td><td><a href="https://etherscan.io/address/0xf3c275d450fe624c1f5e31f3bcb2f8894e96cdf1">0xF3C275D450FE624c1F5E31F3Bcb2F8894E96cDF1</a></td></tr><tr><td>pGHO</td><td><a href="https://etherscan.io/address/0xbb828e3d0c96b334fe2cf8f18382bb11f533e878">0xbB828e3d0c96B334FE2CF8F18382Bb11F533e878</a></td></tr></tbody></table>

## pDebt Addresses

<table><thead><tr><th width="214">Token</th><th>Address</th></tr></thead><tbody><tr><td>pETH Debt</td><td><a href="https://etherscan.io/address/0x81a2b6c536c058ef678ed91212fee48f29ce86d7">0x81a2b6C536c058Ef678eD91212fee48f29Ce86d7</a></td></tr><tr><td>pDAI Debt</td><td><a href="https://etherscan.io/address/0xcc6fb21312f69ef558ec925e00596123cbcf747f">0xcc6Fb21312f69ef558ec925e00596123Cbcf747F</a></td></tr><tr><td>pUSDC Debt</td><td><a href="https://etherscan.io/address/0xd5c341e94674cbb603e74e6065211630c1bab6dc">0xD5c341E94674cBb603E74e6065211630C1bab6dc</a></td></tr><tr><td>pWBTC Debt</td><td><a href="https://etherscan.io/address/0x19fe8c76f62b4cd875db4f2a167e4865797598a5">0x19fE8C76f62B4cd875DB4f2a167e4865797598A5</a></td></tr><tr><td>pwstETH Debt</td><td><a href="https://etherscan.io/address/0xda7f29617b2838829abab9a34d3f98b7bb0a116b">0xda7f29617B2838829AbAB9A34d3F98b7Bb0a116b</a></td></tr><tr><td>pFRAX Debt</td><td><a href="https://etherscan.io/address/0x794a782c2f9a859e1947e371f8621b0838bc423e">0x794A782C2F9A859E1947e371f8621B0838bC423e</a></td></tr><tr><td>prETH Debt</td><td><a href="https://etherscan.io/address/0x40bf200eeee9e172f1f8de99c6c5778a4d33a057">0x40BF200eEeE9e172f1F8de99C6c5778A4d33A057</a></td></tr><tr><td>pUSDT Debt</td><td><a href="https://etherscan.io/address/0x161d33f4b968d714f71c4dface094e961e44ddfa">0x161d33f4B968d714f71C4dFAce094E961e44DdFa</a></td></tr><tr><td>pcbETH Debt</td><td><a href="https://etherscan.io/address/0x11de34ce32147ba4e913470a5013da80fe3eb2b6">0x11dE34Ce32147ba4e913470a5013da80fe3EB2b6</a></td></tr><tr><td>psDAI Debt</td><td><a href="https://etherscan.io/address/0xaa57dd2a403471d9731b6cad914bcc2f0c466a03">0xaA57dd2A403471d9731b6cad914BCC2f0C466a03</a></td></tr><tr><td>pGHO Debt</td><td><a href="https://etherscan.io/address/0xe25d4079f6c303d151dde2e34d1c56d044a1a13d">0xE25D4079f6C303d151DDE2e34D1C56d044A1a13d</a></td></tr></tbody></table>


# Arbitrum

## Deployed Contract Addresses

<table><thead><tr><th width="184">Contract</th><th width="553.3333333333333">Address</th></tr></thead><tbody><tr><td>Notional Proxy</td><td><a href="https://arbiscan.io/address/0x1344a36a1b56144c3bc62e7757377d288fde0369">0x1344A36A1B56144C3Bc62E7757377D288fDE0369</a></td></tr><tr><td>NOTE address</td><td><a href="https://arbiscan.io/token/0x019be259bc299f3f653688c7655c87f998bc7bc1">0x019bE259BC299F3F653688c7655C87F998Bc7bC1</a></td></tr></tbody></table>

## nToken Addresses

<table><thead><tr><th width="252">Token</th><th>Address</th></tr></thead><tbody><tr><td>nETH</td><td><a href="https://arbiscan.io/address/0x18b0Fc5A233acF1586Da7C199Ca9E3f486305A29">0x18b0Fc5A233acF1586Da7C199Ca9E3f486305A29</a></td></tr><tr><td>nDAI</td><td><a href="https://arbiscan.io/address/0x2C42940A06A3F78b3cB7fc62b5fc7DE404c9216f">0x2C42940A06A3F78b3cB7fc62b5fc7DE404c9216f</a></td></tr><tr><td>nUSDC</td><td><a href="https://arbiscan.io/address/0x0F13fb925eDC3E1FE947209010d9c0E072986ADc">0x0F13fb925eDC3E1FE947209010d9c0E072986ADc</a></td></tr><tr><td>nWBTC</td><td><a href="https://arbiscan.io/address/0x52602A1075645845a303f86B2BD0b7E7227f99d6">0x52602A1075645845a303f86B2BD0b7E7227f99d6</a></td></tr><tr><td>nWSTETH</td><td><a href="https://arbiscan.io/address/0x06D45ef1f8b3C37b0de66f156B11F10b4837619A">0x06D45ef1f8b3C37b0de66f156B11F10b4837619A</a></td></tr><tr><td>nFRAX</td><td><a href="https://arbiscan.io/address/0x69633657acfb930d5a97a2662dd32ef1ac8a2f57">0x69633657aCfb930d5A97a2662Dd32ef1aC8a2f57</a></td></tr><tr><td>nRETH</td><td><a href="https://arbiscan.io/address/0x6f6603f12af215bdba1f55f643e098530dd45b8f">0x6f6603f12af215bdba1f55f643e098530dd45b8f</a></td></tr><tr><td>nUSDT</td><td><a href="https://arbiscan.io/address/0x9c0fbb8cade7b178b135fd2f1da125a37b27f442">0x9c0fbb8cade7b178b135fd2f1da125a37b27f442</a></td></tr><tr><td>ncbETH</td><td><a href="https://arbiscan.io/address/0x809B43d2A81A34c4D91BF4815A544d839d0773Bb">0x809B43d2A81A34c4D91BF4815A544d839d0773Bb</a></td></tr></tbody></table>

## pCash Address

<table><thead><tr><th width="252">Token</th><th>Address</th></tr></thead><tbody><tr><td>pETH</td><td><a href="https://arbiscan.io/address/0xabc07bf91469c5450d6941dd0770e6e6761b90d6">0xabc07BF91469C5450D6941dD0770E6E6761B90d6</a></td></tr><tr><td>pDAI</td><td><a href="https://arbiscan.io/address/0x0Ace2DC3995aCD739aE5e0599E71A5524b93b886">0x0Ace2DC3995aCD739aE5e0599E71A5524b93b886</a></td></tr><tr><td>pUSDC</td><td><a href="https://arbiscan.io/address/0x6f28cafe12bd97E474a52bcbfEa6F2c18AE0F53D">0x6f28cafe12bd97E474a52bcbfEa6F2c18AE0F53D</a></td></tr><tr><td>pWBTC</td><td><a href="https://arbiscan.io/address/0xB9bFBB35C2eD588a42f9Fd1120929c607B463192">0xB9bFBB35C2eD588a42f9Fd1120929c607B463192</a></td></tr><tr><td>pWSTETH</td><td><a href="https://arbiscan.io/address/0xbC323E3564Fb498E55CDc83a3Ea6bB1AF8402D6B">0xbC323E3564Fb498E55CDc83a3Ea6bB1AF8402D6B</a></td></tr><tr><td>pFRAX</td><td><a href="https://arbiscan.io/address/0x1fd865a55eaf5333e6374Fb3Ad66D22e9885d3Aa">0x1fd865a55eaf5333e6374Fb3Ad66D22e9885d3Aa</a></td></tr><tr><td>pRETH</td><td><a href="https://arbiscan.io/address/0x866eb09d3d1397b8a28cfe5dceeaed9362840385">0x866eb09d3d1397b8a28cfe5dceeaed9362840385</a></td></tr><tr><td>pUSDT</td><td><a href="https://arbiscan.io/address/0xd63ace62b925361fc588734022718e919a8081ac">0xd63ace62b925361fc588734022718e919a8081ac</a></td></tr><tr><td>pcbETH</td><td><a href="https://arbiscan.io/address/0xa135d7f10545e3a45e24e79ecd4e4c3c78cf56bf">0xA135D7f10545e3a45e24e79eCD4e4c3c78cF56Bf</a></td></tr><tr><td>pUNI</td><td><a href="https://arbiscan.io/address/0x8652de5310746e8de24cbe17ee8b5fe1e78febcc">0x8652De5310746E8DE24Cbe17Ee8b5FE1e78febcC</a></td></tr><tr><td>pLINK</td><td><a href="https://arbiscan.io/address/0x63ffcfb69edf8c9cb19a36401cf88c8939c40650">0x63FfCFb69EDF8C9cB19a36401cf88C8939C40650</a></td></tr><tr><td>pLDO</td><td><a href="https://arbiscan.io/address/0xef3f53046c9b00702f25186d7342d73c789f547a">0xef3F53046c9b00702f25186D7342d73C789F547a</a></td></tr><tr><td>pRDNT</td><td><a href="https://arbiscan.io/address/0x0519614643a019feb53b9f2c395b243253f75db7">0x0519614643A019fEb53B9F2C395B243253f75DB7</a></td></tr><tr><td>pGMX</td><td><a href="https://arbiscan.io/address/0x6d13d3c51e75f9970733ff8c32715773e1ed73c4">0x6d13D3C51e75f9970733ff8C32715773e1eD73C4</a></td></tr></tbody></table>

## pDebt Address

<table><thead><tr><th width="252">Token</th><th>Address</th></tr></thead><tbody><tr><td>pETHdebt</td><td><a href="https://arbiscan.io/address/0x6ebce2453398af200c688c7c4ebd479171231818">0x6EbcE2453398af200c688C7c4eBD479171231818</a></td></tr><tr><td>pDAIdebt</td><td><a href="https://arbiscan.io/address/0x4068A40E229C9e8DF8DEaf716266ef008d673EFE">0x4068A40E229C9e8DF8DEaf716266ef008d673EFE</a></td></tr><tr><td>pUSDCdebt</td><td><a href="https://arbiscan.io/address/0xc3882b132011ff3cEa4da81F3303138368dd5D75">0xc3882b132011ff3cEa4da81F3303138368dd5D75</a></td></tr><tr><td>pWBTCdebt</td><td><a href="https://arbiscan.io/address/0xc12d27954d9122D971c67eF188736f36629FF958">0xc12d27954d9122D971c67eF188736f36629FF958</a></td></tr><tr><td>pWSTETHdebt</td><td><a href="https://arbiscan.io/address/0x41BE0117864dc317D1Cc8100B01c8Ac90da3BA90">0x41BE0117864dc317D1Cc8100B01c8Ac90da3BA90</a></td></tr><tr><td>pFRAXdebt</td><td><a href="https://arbiscan.io/address/0x452F5c6238c05E980a235f63dBc11bFBe004cc56">0x452F5c6238c05E980a235f63dBc11bFBe004cc56</a></td></tr><tr><td>pRETHdebt</td><td><a href="https://arbiscan.io/address/0x7366d16800c3ca83a085e193ae626d7d565d13b3">0x7366d16800c3ca83a085e193ae626d7d565d13b3</a></td></tr><tr><td>pUSDTdebt</td><td><a href="https://arbiscan.io/address/0x2ddb08f2757909537bdf2d2eb2bd4f7a64e8e5dd">0x2ddb08f2757909537bdf2d2eb2bd4f7a64e8e5dd</a></td></tr><tr><td>pcbETH</td><td><a href="https://arbiscan.io/address/0x4ee6573a7bf74f6dfed54bc9a9de15a81b92e081">0x4eE6573a7bf74f6DFeD54bc9A9DE15a81b92e081</a></td></tr><tr><td>pUNI</td><td><a href="https://arbiscan.io/address/0x692749e5bd565c37f5f562f71b335eefe046eaa0">0x692749e5bD565C37F5f562F71B335EeFe046eaA0</a></td></tr><tr><td>pLINK</td><td><a href="https://arbiscan.io/address/0x3482db39b1ffdfa3ca99f0f829aab0855088e707">0x3482Db39B1fFdFA3ca99F0f829AAb0855088E707</a></td></tr><tr><td>pLDO</td><td><a href="https://arbiscan.io/address/0xc9c5e5f79738ddd3924c6f02356291eace665ea3">0xC9C5E5f79738DdD3924C6f02356291eace665EA3</a></td></tr><tr><td>pRDNT</td><td><a href="https://arbiscan.io/address/0xfbd9e818ac30311896f7d7e5bc18f613ba644b56">0xfBD9e818aC30311896F7d7e5BC18f613BA644B56</a></td></tr><tr><td>pGMX</td><td><a href="https://arbiscan.io/address/0x65ea9aff1b12fc8dac52a9e07ce2928741159a6c">0x65EA9aff1B12fC8DAC52a9E07CE2928741159a6c</a></td></tr></tbody></table>


# Audits

Notional invests in thorough testing and auditing of Notional smart contracts. Here is the list of the multiple [security audits](https://github.com/notional-finance/contracts-v2/blob/master/audits/README.md) Notional underwent:

* [Notional V1, Open Zeppelin | Dec 2020](https://blog.openzeppelin.com/notional-audit/)
* [Notional V2 Governance, Open Zeppelin | Nov 2021](https://blog.openzeppelin.com/notional-v2-audit-governance-contracts/)
* [Notional V2, ABDK | Sept 2021](https://github.com/notional-finance/contracts-v2/blob/master/audits/ABDK%20-%20Notional%20V2%2C%20Sept%201%202021.pdf)
* [Notional V2, Certora | Nov 2021](https://github.com/notional-finance/contracts-v2/blob/master/audits/Certora%20-%20Formal%20Verfication%20Report%2C%20Nov%201%202021.pdf)
* [Notional V2, ABDK Fixes | Nov 2021](https://github.com/notional-finance/contracts-v2/blob/master/audits/ABDK%20-%20Notional%20V2%20Fixes%2C%20Nov%201%202021.pdf)
* [Notional V2, Code Arena | Oct 2021](https://code4rena.com/reports/2021-08-notional/)
* [Staked NOTE | Mar 2022](https://code4rena.com/reports/2022-01-notional/)
* [Notional V2.1, Consensys Diligence | Mar 2022](https://consensys.net/diligence/audits/2022/03/notional-protocol-v2.1/)
* [Wrapped fCash, Code Arena | Jul 2022](https://code4rena.com/reports/2022-06-notional-coop/)
* [Leveraged Vaults, Consensys Diligence | Jul 2022](https://consensys.net/diligence/audits/2022/07/notional-finance/)
* [Leveraged Vaults + Balancer Vault Strategy, Sherlock | Oct 2022](https://app.sherlock.xyz/audits/contests/2)
* [Balancer Vault Strategy Fixes, Sherlock | Jan 2023](https://app.sherlock.xyz/audits/contests/31)
* [Convex Leveraged Vault, Sherlock | Mar 2023](https://app.sherlock.xyz/audits/contests/52)
* [Notional V3, Sherlock | May 2023](https://app.sherlock.xyz/audits/contests/59)
* [Single Sided LP Leveraged Vaults | Nov 2023](https://audits.sherlock.xyz/contests/119)
* [External Lending, Wrapped fCash | Jan 2024](https://audits.sherlock.xyz/contests/142)
* [Pendle PTs, Vault Incentives | June 2024](https://audits.sherlock.xyz/contests/446?filter=questions)

  <br>


# Bug Bounty

[Notional V3 contracts ](https://github.com/notional-finance)are open source for Security Auditors to review the code base.

Notional has an active [bug bounty program ](https://immunefi.com/bounty/notional/)through Immunefi. Security researchers can contact Notional's security team at <security@notional.finance>.


# Currency Ids

Each currency listed on Notional is associated with a unique Currency Id. The Currency Id of a given asset can vary on different Notional deployments. &#x20;

| Currency Id | Ethereum Mainnet                                                                | Arbitrum                                                                                                                   |
| ----------- | ------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| 1           | [ETH](https://www.youtube.com/watch?v=rlM7gsUY9Gw)                              | [ETH](https://www.youtube.com/watch?v=rlM7gsUY9Gw)                                                                         |
| 2           | [DAI](https://etherscan.io/token/0x6b175474e89094c44da98b954eedeac495271d0f)    | [DAI](https://arbiscan.io/address/0xda10009cbd5d07dd0cecc66161fc93d7c9000da1)                                              |
| 3           | [USDC](https://etherscan.io/token/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48)   | [USDC.e](https://arbiscan.io/token/0xff970a61a04b1ca14834a43f5de4533ebddb5cc8)                                             |
| 4           | [WBTC](https://etherscan.io/token/0x2260fac5e5542a773aa44fbcfedf7c193bc2c599)   | [WBTC](https://arbiscan.io/address/0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f)                                             |
| 5           | [wstETH](https://etherscan.io/token/0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0) | [wstETH](https://arbiscan.io/address/0x5979D7b546E38E414F7E9822514be443A4800529)                                           |
| 6           | [FRAX](https://etherscan.io/token/0x853d955acef822db058eb8505911ed77f175b99e)   | [FRAX](https://arbiscan.io/address/0x17fc002b466eec40dae837fc4be5c67993ddbd6f)                                             |
| 7           | [rETH](https://etherscan.io/token/0xae78736cd615f374d3085123a210448e74fc6393)   | [rETH](https://arbiscan.io/token/0xec70dcb4a1efa46b8f2d97c310c9c4790ba5ffa8)                                               |
| 8           | [USDT](https://etherscan.io/token/0xdac17f958d2ee523a2206206994597c13d831ec7)   | [USDT](https://arbiscan.io/token/0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9)                                               |
| 9           | [cbETH](https://etherscan.io/token/0xbe9895146f7af43049ca1c1ae358b0541ea49704)  | [cbETH](https://arbiscan.io/token/0x1debd73e752beaf79865fd6446b0c970eae7732f?a=0x7235a73bd38f26e16bc146b1d5173f4ca5172a42) |
| 10          | [sDAI](https://etherscan.io/token/0x83f20f44975d03b1b09e64809b757c47f942beea)   | [GMX](https://arbiscan.io/token/0xfc5a1a6eb076a2c7ad06ed22c90d7e710e35ad0a)                                                |
| 11          | [GHO](https://etherscan.io/token/0x40d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f)    | [ARB](https://arbiscan.io/token/0x912ce59144191c1204e64559fe8253a0e49e6548)                                                |
| 12          | [tBTC](https://etherscan.io/token/0x18084fba666a33d37592fa2633fd49a74dd93a88)   | [RDNT](https://arbiscan.io/token/0x3082cc23568ea640225c2467653db90e9250aaa0)                                               |
| 13          | N/A                                                                             | [UNI](https://arbiscan.io/token/0xfa7f8980b0f1e64a2062791cc3b0871572f1f7f0)                                                |
| 14          | N/A                                                                             | [LINK](https://arbiscan.io/token/0xf97f4df75117a78c1a5a0dbb814af92458539fb4)                                               |
| 15          | N/A                                                                             | [LDO](https://arbiscan.io/token/0x13ad51ed4f1b7e9dc168d8a00cb3f4ddd85efa60)                                                |
| 16          | N/A                                                                             | [tBTC](https://arbiscan.io/token/0x6c84a8f1c29108F47a79964b5Fe888D4f4D0dE40)                                               |


# Market Indexes

fCash markets of a given currency are identified by Market Indexes. Market Indexes identify the tenor of active markets using a predefined tenor cadence:&#x20;

* 3 month (market index = 1)
* 6 month (market index = 2)
* 1 year (market index = 3)
* 2 year (market index = 4)
* 5 year (market index = 5)
* 10 year (market index = 6)
* 20 year (market index = 7)

As an example, using a market index of 1 would refer to a 3 Month fCash market and a market with an index of 3 would refer to a 1 Year fCash market.&#x20;


# Notional Internal Precision

## Balances

Notional's internal balance precision is 8 decimals. For example, here is a non-exhaustive list of balance related variables with 1e8 precision:

* User Prime Cash and Prime Debt balances
* User nToken balances
* User fCash balances
* nToken liquidity token balances
* User Vault Share Balances
* User Free Collateral balances
* fCash markets total Prime Cash and total fCash balances
* Prime Cash totalUnderlyingSupply balances
* maxUnderlyingSupply parameters&#x20;
* Leveraged Vaults minAccountBorrowSize parameters

## Rates

Notional's internal rate precision is 9 decimals. For example, here is a non-exhaustive list of rates related variables with 1e9 precision:

* `fCashOracleRates`
* `fCashLastImpliedRates`
* `oracleSupplyRate`
* Leveraged Vaults `minCollateralRatio`, `maxRequiredAccountCollateralRatio`, `maxDeleverageCollateralRatio`, `liquidationRate`, and `feeRate` parameters

## Scalars

Prime Cash scalars are 1e18 precision. For example, the precision of the following variables is 1e18:

* `debtScalar`
* `supplyScalar`
* `underlyingScalar`

## Prime factors

The Prime Cash `debtFactor`and `supplyFactor` precision is 1e36.


# Intro

This section will cover how to interact with Notional V3 contracts using [ETH brownie](https://eth-brownie.readthedocs.io/en/stable/install.html) a Python-based development and testing framework.

## Contract Github repository

Notional's V3 smart contracts repository can be found [here](https://github.com/notional-finance/).

## Setup

Here is a simple setup to start interacting with Notional V3 using ETH brownie:

```
import json
from brownie import (
    accounts, 
    interface
)
from brownie.network.state import Chain
import eth_abi

class V3Environment:
    def __init__(self):
        self.notional = interface.NotionalProxy("0x1344A36A1B56144C3Bc62E7757377D288fDE0369")
        self.owner = self.notional.owner()

def main():
    env = V3Environment()
    env.chain = Chain()
    env.notional.address
```

## Contract approval

To interact with the protocol using ERC-20 tokens, accounts must approve Notional's Proxy.

```
# Approve sending an unlimited amount of DAI to the Notional Proxy.
interface.ERC20(currencyAddress).approve(notional.address, 2**255, {'from': account}) 
```


# Trading guide

In this section we will cover how one can:

* Deposit&#x20;
* Lend at the Prime Variable Rate
* Borrow at the Prime Borrow Rate
* Buy fCash (Lend Fixed)
* Sell fCash (Borrow Fixed)
* Mint nTokens (Provide Liquidity)
* Redeem nTokens (Redeem Liquidity)
* Enter a leveraged vault
* Exit a leveraged vault

We will also explore how to submit multiple actions in one trade and how to set slippage limits when trading fCash.&#x20;

## Helper functions

Here are some helper functions that can be useful when interacting with Notional balance and trading functions:

```
from eth_abi.packed import encode_abi_packed

DEPOSIT_ACTION_TYPE = {
    "None": 0,
    "DepositAsset": 1,
    "DepositUnderlying": 2,
    "DepositAssetAndMintNToken": 3,
    "DepositUnderlyingAndMintNToken": 4,
    "RedeemNToken": 5,
    "ConvertCashToNToken": 6,
}

TRADE_ACTION_TYPE = {
    "Lend": 0,
    "Borrow": 1,
    "AddLiquidity": 2,
    "RemoveLiquidity": 3,
    "PurchaseNTokenResidual": 4,
    "SettleCashDebt": 5,
}

def get_balance_action(currencyId, depositActionType, **kwargs):
    depositActionAmount = (
        0 if "depositActionAmount" not in kwargs else kwargs["depositActionAmount"]
    )
    withdrawAmountInternalPrecision = (
        0
        if "withdrawAmountInternalPrecision" not in kwargs
        else kwargs["withdrawAmountInternalPrecision"]
    )
    withdrawEntireCashBalance = (
        False if "withdrawEntireCashBalance" not in kwargs else kwargs["withdrawEntireCashBalance"]
    )
    redeemToUnderlying = (
        True if "redeemToUnderlying" not in kwargs else kwargs["redeemToUnderlying"]
    )

    return (
        DEPOSIT_ACTION_TYPE[depositActionType],
        currencyId,
        int(depositActionAmount),
        int(withdrawAmountInternalPrecision),
        withdrawEntireCashBalance,
        redeemToUnderlying,
    )


def get_balance_trade_action(currencyId, depositActionType, tradeActionData, **kwargs):
    tradeActions = [get_trade_action(**t) for t in tradeActionData]
    balanceAction = list(get_balance_action(currencyId, depositActionType, **kwargs))
    balanceAction.append(tradeActions)
    return tuple(balanceAction)


def get_lend_action(currencyId, tradeActionData, depositUnderlying):
    tradeActions = [get_trade_action(**t) for t in tradeActionData]
    return (currencyId, depositUnderlying, tradeActions)


def get_trade_action(**kwargs):
    tradeActionType = kwargs["tradeActionType"]

    if tradeActionType == "Lend":
        return encode_abi_packed(
            ["uint8", "uint8", "uint88", "uint32", "uint120"],
            [
                TRADE_ACTION_TYPE[tradeActionType],
                kwargs["marketIndex"],
                int(kwargs["notional"]),
                int(kwargs["minSlippage"]),
                0,
            ],
        )
    elif tradeActionType == "Borrow":
        return encode_abi_packed(
            ["uint8", "uint8", "uint88", "uint32", "uint120"],
            [
                TRADE_ACTION_TYPE[tradeActionType],
                kwargs["marketIndex"],
                int(kwargs["notional"]),
                int(kwargs["maxSlippage"]),
                0,
            ],
        )
    elif tradeActionType == "AddLiquidity":
        return encode_abi_packed(
            ["uint8", "uint8", "uint88", "uint32", "uint32", "uint88"],
            [
                TRADE_ACTION_TYPE[tradeActionType],
                kwargs["marketIndex"],
                int(kwargs["notional"]),
                int(kwargs["minSlippage"]),
                int(kwargs["maxSlippage"]),
                0,
            ],
        )
    elif tradeActionType == "RemoveLiquidity":
        return encode_abi_packed(
            ["uint8", "uint8", "uint88", "uint32", "uint32", "uint88"],
            [
                TRADE_ACTION_TYPE[tradeActionType],
                kwargs["marketIndex"],
                int(kwargs["notional"]),
                int(kwargs["minSlippage"]),
                int(kwargs["maxSlippage"]),
                0,
            ],
        )
    elif tradeActionType == "PurchaseNTokenResidual":
        return encode_abi_packed(
            ["uint8", "uint32", "int88", "uint128"],
            [
                TRADE_ACTION_TYPE[tradeActionType],
                kwargs["maturity"],
                int(kwargs["fCashAmountToPurchase"]),
                0,
            ],
        )
    elif tradeActionType == "SettleCashDebt":
        return encode_abi_packed(
            ["uint8", "address", "uint88"],
            [
                TRADE_ACTION_TYPE[tradeActionType],
                kwargs["counterparty"],
                int(kwargs["amountToSettle"]),
            ],
        )


```


# Deposit (Prime Lend)

## Deposit a single Currency to a Notional account

To deposit underlying tokens to Notional, users can use the `depositUnderlyingToken` method:

<pre><code><strong># Deposit DAI on Notional. DAI external precision is 1e18.
</strong><strong>notional.depositUnderlyingToken(account.address, 2, 10e18, {'from': account})
</strong>
# Deposit 100 USDC on Notional. USDC external precision is 1e6.
notional.depositUnderlyingToken(account.address, 2, 100e6, {'from': account})

# Deposit 1 ETH on Notional
notional.depositUnderlyingToken(account.address, 1, 1e18, {'from': account, 'value':1e18})

</code></pre>

## Deposit Prime Cash to a Notional Account

To deposit Prime Cash to Notional, users can use the `depositAssetToken` method:

```
# Deposit 10 pDAI to a Notional Account. pCash external precision is 1e8.
notional.depositAssetToken(account.address, 2, 10e8, {'from': account})

# Deposit 100 pUSDC to a Notional Account. pCash external precision is 1e8.
notional.depositAssetToken(account.address, 3, 100e8, {'from': account})

# Deposit 1 pETH to a Notional Account. pCash external precision is 1e8.
notional.depositAssetToken(account.address, 1, 1e8, {'from': account})
```

## Batch deposit to a Notional Account

To deposit multiple tokens to Notional at once, users can use the `batchBalanceAction` method:

```
from helpers import get_balance_action

# Deposit 100 DAI & 10 USDC
depositActionDAI = get_balance_action(2, "DepositUnderlying", depositActionAmount=100e18)
depositActionUSDC = get_balance_action(3, "DepositUnderlying", depositActionAmount=10e6)

tx = notional.batchBalanceAction(account.address, [depositActionDAI, depositActionUSDC], {'from': account})
```

*Note that the array of actions must be sorted by currency ids when using batch functions.*


# Trade fCash (Borrow & Lend Fixed)

## Deposit and Lend Fixed

To lend fixed on Notional, users need to trade Prime Cash in exchange for fCash:

```
from helpers import get_balance_trade_action

# Deposit 10 DAI to Notional as Prime Dai and lend 5 fDAI fixed in the 3M maturity (marketIndex = 1). 
lendActionDai = get_balance_trade_action(2, "DepositUnderlying", [
    {"tradeActionType": "Lend", "marketIndex": 1, "notional": 5 * 1e8, "minSlippage": 0.03*1e9}
    ], depositActionAmount = 10e18)

tx = notional.batchBalanceAndTradeAction(account.address, [lendActionDai], {"from": account})
```

Note that the `minSlippage` limit sets the minimum fixed rate at which the user will lend. The transaction will revert if the trade implied fixed rate is lower than the minimum slippage limit.

The `depositActionAmount` uses the external currency precision. The `notional` amount precision is 1e8. The slippage limit rate precision is 1e9.

## Deposit and Lend Fixed in multiple maturities

Users can use the `batchBalanceAndTradeAction` method to lend across multiple maturities:

```
from helpers import get_balance_trade_action

# Deposit 10 DAI to Notional as Prime Dai, 
# Lend 5 fDAI fixed in the 3M maturity (marketIndex = 1), and 
# Lend 3 fDAI fixed in the 6M maturity (marketIndex = 2).
lendActionDai = get_balance_trade_action(2, "DepositUnderlying", [
        {"tradeActionType": "Lend", "marketIndex": 1, "notional": 5 * 1e8, "minSlippage": 0.03*1e9},
        {"tradeActionType": "Lend", "marketIndex": 2, "notional": 3 * 1e8, "minSlippage": 0.02*1e9}
        ], depositActionAmount = 10e18)

tx = notional.batchBalanceAndTradeAction(account.address, [lendActionDai], {"from": account})
```

## Deposit and Lend Fixed in multiple currencies

Users can use the `batchBalanceAndTradeAction` method to lend across multiple currencies:

```
from helpers import get_balance_trade_action

# Deposit 10 DAI to Notional as Prime DAI and lend 5 fDAI fixed in the 3M maturity (marketIndex = 1). 
# Deposit 100 USDC to Notional as Prime USDC and lend 100 fUSDC fixed in the 6M maturity (marketIndex = 2).
lendActionDai = get_balance_trade_action(2, "DepositUnderlying", [
        {"tradeActionType": "Lend", "marketIndex": 1, "notional": 5 * 1e8, "minSlippage": 0.03*1e9}
        ], depositActionAmount = 10e18)
lendActionUsdc = get_balance_trade_action(3, "DepositUnderlying", [
        {"tradeActionType": "Lend", "marketIndex": 2, "notional": 100 * 1e8, "minSlippage": 0.02*1e9}
        ], depositActionAmount = 100e6)

tx = notional.batchBalanceAndTradeAction(account.address, [lendActionDai, lendActionUsdc], {"from": account})
```

Note that when using batch functions the array of actions needs to be sorted by Currency Ids.

## Deposit, lend fixed in the 3M maturity and borrow in the 6M maturity

Users can use the `batchBalanceAndTradeAction` method to lend and borrow across different maturities:

```
from helpers import get_balance_trade_action

# Deposit 10 DAI to Notional as Prime Dai, 
# Lend 1,000 fDAI fixed in the 3M maturity (marketIndex = 1), and 
# Borrow 1,000 fDAI fixed in the 6M maturity (marketIndex = 2).
actionDai = get_balance_trade_action(2, "DepositUnderlying", [
        {"tradeActionType": "Lend," "marketIndex": 1, "notional": 1_000 * 1e8, "minSlippage": 0.03*1e9},
        {"tradeActionType": "Borrow", "marketIndex": 2, "notional": 1_000 * 1e8, "maxSlippage": 0.05*1e9}
        ], depositActionAmount = 10e18)

tx = notional.batchBalanceAndTradeAction(account.address, [actionDai], {"from": account})
```

Note that the maxSlippage limit sets the maximum fixed rate at which user will borrow. If the trade implied fixed rate is lower than the minimum slippage limit, the transaction will revert.

## Deposit Prime Cash in one currency and borrow fixed in another currency

Users can use the `batchBalanceAndTradeAction` method to borrow at a fixed rate:

```
from helpers import get_balance_trade_action

# Deposit 10 DAI to Notional as Prime Dai, 
# Borrow 5 fUSDC fixed in the 6M maturity (marketIndex = 2).
actionDai = get_balance_trade_action(2, "DepositUnderlying", [], depositActionAmount = 10e18)
actionUsdc = get_balance_trade_action(3, "None", [
        {"tradeActionType": "Borrow", "marketIndex": 2, "notional": 5 * 1e8, "maxSlippage": 0.05*1e9}
        ], withdrawEntireCashBalance=True)

tx = notional.batchBalanceAndTradeAction(account.address, [actionDai, actionUsdc], {"from": account})
```

Note that we can set `withdrawEntireCashBalance` to True in order to withdraw the borrowed USDC to the user's wallet.


# Add liquidity (Mint nTokens)

## Deposit from wallet and Mint nTokens

Users can use the `batchBalanceAction` method to mint nTokens across multiple maturities:

```
# Deposit 100 DAI and 1 WBTC and Mint nDAI and nWBTC LP tokens.

mintNDaiAction = get_balance_action(2, "DepositUnderlyingAndMintNToken", depositActionAmount=10e18)
mintNWbtcAction = get_balance_action(4, "DepositUnderlyingAndMintNToken", depositActionAmount=1e8)
notional.batchBalanceAction(account.address, [mintNDaiAction, mintNWbtcAction], {"from": account})
```


# Withdraw liquidity (Redeem nTokens)

## Redeem nTokens (sell asset and don't accept residuals)

```
# Redeem 100 nDAI. Sell fDAI residuals to Prime DAI and don't accept fDAI residuals. 
notional.nTokenRedeem(account.address, 2, 100e8, True, False, {'from': account})
```

Note that by setting `sellTokenAssets` to True and `acceptResidualAssets` to False, the nToken redeemer will only receive Prime DAI in exchange for his nDAI. If the nDAI account has accrued any fDAI residuals, they will be sold for Prime Cash during the redeem action. Trading fCash for Prime Cash is subject to fCash trading fees. A large nToken redemption might therefore lead the redeemer to face slippage when redeeming.&#x20;

## Redeem nTokens (don't sell asset and accept residuals)

```
# Redeem 100 nDAI. Don't sell fDAI residuals to Prime DAI and accept fDAI residuals.
notional.nTokenRedeem(account.address, 2, 100e8, False, True, {'from': account})
```

Note that by setting `sellTokenAssets` to False and `acceptResidualAssets` to True, the nToken redeemer will likely receive fDAI in all maturities and some Prime DAI.

## Redeem nTokens (sell asset and accept residuals)

```
# Redeem 100 nDAI. Sell fDAI residuals to Prime DAI and accept fDAI residuals.
notional.nTokenRedeem(account.address, 2, 100e8, True, True, {'from': account})
```

Note that by setting `sellTokenAssets` to True and `acceptResidualAssets` to True, the nToken redeemer will trade fDAI residuals for Prime DAI. If selling residuals is impossible due to low fCash liquidity, the redeemer will receive the fCash residuals assets to his portfolio.


# Withdraw (Prime Cash)

## Withdraw a Prime Cash Balance from Notional

Users can use the `withdraw` method to redeem their Prime Cash balances from Notional:&#x20;

```
# Redeem 100 Prime USDC from Notional to a user's wallet in USDC. 
tx = notional.withdraw(3, 100e8, True, {'from': account})

# Withdraw 100 Prime USDC from Notional to a user's wallet in Prime USDC.
tx = notional.withdraw(3, 100e8, False, {'from': account})
```

Note that the Prime Cash balance precision is 1e8.&#x20;

## Withdraw Prime Cash from Notional (Borrow Prime)

Users can use the `withdraw` method to borrow Prime Debts from Notional:

```
# Deposit 100 USDC on Notional. USDC external precision is 1e6.
notional.depositUnderlyingToken(account.address, 2, 100e6, {'from': account})

# In order to Borrow Prime Cash the user needs to enable Prime Borrow.
notional.enablePrimeBorrow(True, {'from': account})

# Borrow 50 Prime DAI from Notional to the user's wallet in DAI.
tx = notional.withdraw(3, 50e8, True, {'from': account})
```


# Settle Account

## Settle Account

Users can settle Notional accounts using the settleAccount function. If a user trades after a settlement, it will also automatically settle his account.

```
# Accounts holding fCash balances (positive or negative) in the 3M maturity need to 
be settled after the fCash maturity has passed and markets have been initialized.

notional.settleAccount(settledAccount, {'from': account})
```


# Enter Leveraged Vaults

## Enter Leveraged Vault

Notional users can use the `enterVault` method to initiate or update a vault position:&#x20;

```
def get_deposit_params(minPoolClaim=0, trade=bytes()):
    return eth_abi.encode_abi(
        ['(uint256, bytes)'],
        [[minPoolClaim, trade]]
        )

depositParams = get_deposit_params()

# Enter a vault by depositing 10 USDC, borrowing 20 fUSDC from Notional in the December 18, 2023 (1702944000) maturity with a max borrow interest rate limit of 5%.
notional.enterVault(account.address, vaultAddress, 10e6, 1702944000, 25e8, 0.05 * 1e9, depositParams, {'from':account})
```

A user can enter a vault at a specific leverage ratio by selecting the amount of Prime Cash he borrows and the deposit amount.&#x20;


# Exit Leveraged Vaults

## Exit Leveraged Vault

Notional users can use the `exitVault` method to exit or update a vault position:&#x20;

```
# Exit a vault (USDC borrow) by redeeming the account's vault shares and repaying its fCash debt.

vaultShares = notional.getVaultAccount(account.address, vaultAddress)["vaultShares"]
fCash = abs(notional.getVaultAccount(account.address, vaultAddress)["accountDebtUnderlying"])
tx = notional.exitVault(account.address, vaultAddress, account.address, vaultShares, fCash, 0, "", {'from': account})
```

A user could increase his leverage ratio by partially redeeming his vault shares without repaying his debt position.


# Accounts

To get a list of Notional users, one can use this [subgraph query](/v3-technical-docs/subgraph-guides/notional-v3-subgraphs/fetch-notional-accounts) or use this [Dune query](https://dune.com/queries/2759293). &#x20;

## Get an account's balances

```
account = notional.getAccount(accountAddress)
```

## Fetch an account's positions in readable format

The following function can be used to make an account's balances more readable. This is especially useful when comparing an account's state before and after trading.

<pre><code>from datetime import datetime
<strong>
</strong><strong># CurrencyId to Symbol Mapping
</strong>CURRENCY_ID_TO_SYMBOL = {
    1: "ETH",
    2: "DAI",
    3: "USDC",
    4: "WBTC",
    5: "wstETH",
    6: "FRAX",
    7: "rETH",
    8: "USDT",
}

# This function can be used to make an account's positions readable.
def getAccountPositions(address):
        account = notional.getAccount(address)
        dict = {}
        dict['Account Address'] = address
        dict['Free collateral (ETH)'] = notional.getFreeCollateral(address)[0] / 1e8

        for i in account[1]:
            if i[0] != 0:
                symbol = CURRENCY_ID_TO_SYMBOL[i[0]]
                dict[symbol] = {
                    'p{} Balance'.format(symbol): i[1]/1e8,
                    'n{} Balance'.format(symbol): i[2]/1e8} 

        for j in account[2]:
            symbol = CURRENCY_ID_TO_SYMBOL[j[0]]
            if j[2] == 1:
                dict[symbol].update({'f{} {} {}'.format(symbol, j[1], datetime.fromtimestamp(j[1]).date()): j[3] / 1e8})
        return dict
</code></pre>

## Get an account's free collateral

If a user's free collateral is negative, then the user is eligible to get liquidated. If the user's free collateral figure is positive the account is sufficiently collateralized.

```
notional.getFreeCollateral(accountAddress)
```

## Get an account's Leveraged Vaults positions

Users can use the `getVaultAccount` methord to fetch an account's leveraged vault positions: &#x20;

<pre><code><strong>leveragedVaultAccount = notional.getVaultAccount(accountAddress, vaultAdderes)
</strong>accountVaultShares = leveragedVaultAccount["vaultShares"]/1e8
accountDebtInUnderlying = leveragedVaultAccount["accountDebtUnderlying"]/1e8
</code></pre>


# Prime Cash Markets

## Fetch Prime Cash and Prime Debt Addresses

```
# Fetch the Prime Cash and Prime debt addresses for a given currencyId

pCashAddress = notional.pCashAddress(currrencyId)
pDebtAddress = notional.pDebtAddress(currrencyId)
```

## Fetch a market's total pCash and total pDebt supply

```
from brownie.network.state import Chain
chain = Chain()

primeFactors = notional.getPrimeFactorsStored(currencyId, chain.time())
totalPrimeSupply = primeFactors['factors']["totalPrimeSupply"]/1e8
totalPrimeDebt = primeFactors['factors']["totalPrimeDebt"]/1e8
```

## Get a market's pCash and pDebt Supply in Underlying

In order to convert Prime Cash to underlying we need to use the underlyingScalar and the supplyScalar. To convert Prime Debt to underlying we need to use the underlyingScalar and the debtScalar:&#x20;

```
from brownie.network.state import Chain
chain = Chain()

primeFactors = notional.getPrimeFactorsStored(currencyId, chain.time())
totalPrimeSupply = primeFactors['factors']["totalPrimeSupply"]/1e8
totalPrimeDebt = primeFactors['factors']["totalPrimeDebt"]/1e8

supplyScalar = primeFactors["factors"]["supplyScalar"]/1e18
debtScalar = primeFactors["factors"]["debtScalar"]/1e18
underlyingScalar = primeFactors["factors"]["underlyingScalar"]/1e18

# Total Prime Supply in underlying 
totalPrimeSupplyInUnderlying = totalPrimeSupply * underlyingScalar * supplyScalar
totalPrimeDebtInUnderlying = totalPrimeDebt * underlyingScalar * debtScalar 

```

## Calculate a Prime Cash Market's utilization

Prime Cash Market utilization is defined as a market's `debt / supply` in underlying terms:

```
from brownie.network.state import Chain
chain = Chain()

primeFactors = notional.getPrimeFactorsStored(currencyId, chain.time())
totalPrimeSupply = primeFactors["factors"]["totalPrimeSupply"]
totalPrimeDebt = primeFactors["factors"]["totalPrimeDebt"]
supplyScalar = primeFactors["factors"]["supplyScalar"]
debtScalar = primeFactors["factors"]["debtScalar"]


# Utilization is calculated in underlying terms.
# Utilization = accruedDebtUnderlying / accruedSupplyUnderlying
# Utilization = (totalPrimeDebt * underlyingScalar * debtScalar) / (totalPrimeSupply * underlyingScalar * supplyScalar)
# Note that the underlyingScalar cancels out in both numerator and denominator
utilization = (totalPrimeDebt * debtScalar) / (totalPrimeSupply * supplyScalar) 

```

## Fetch Prime Cash markets Supply Rates and Borrowing Rates

<pre><code>from brownie.network.state import Chain
chain = Chain()

<strong>primeFactors = notional.getPrimeFactors(currencyId, chain.time())
</strong><strong>
</strong># Prime Cash Supply Rate
oracleSupplyRate = primeFactors["primeRate"]["oracleSupplyRate"]/1e9

# Prime Cash Borrow Rate
TODO after contract upgrade

</code></pre>


# fCash Markets

## Get active fCash Markets

We can use the `getActiveMarkets` method to get a list of the current active markets in a given currency:

```
 activeMarkets = notional.getActiveMarkets(currencyId)
```

## Get a market's total fCash and total Prime Cash holdings

```
market3Months = activeMarkets[0]
market6Months = activeMarkets[1]

# Get the maturity of the 3 Month market
maturity = market3Months[1]

# Get the 3 Month market total Prime Cash balance 
primeCashBalance3MonthMarket = market3Months[3]/1e8

# Get the 3 Month market total fCash balance
fCashBalance3MonthMarket  = market3Months[2]/1e8
```

## Get a market's utilization

An fCash market's utilization is defined as total `fCash/ (total fCash + total Prime Cash in underlying)`:&#x20;

<pre><code>from brownie.network.state import Chain
chain = Chain()

primeFactors = notional.getPrimeFactorsStored(currencyId, chain.time())
supplyScalar = primeFactors["factors"]["supplyScalar"]/1e18
underlyingScalar = primeFactors["factors"]["underlyingScalar"]/1e18

<strong>marketPrimeCashSupply = primeCashBalance3MonthMarket * underlyingScalar * supplyScalar
</strong><strong>fCashMarketUtilization =  fCashBalance3MonthMarket / (fCashBalance3MonthMarket + marketPrimeCashSupply) 
</strong><strong>
</strong></code></pre>

## Get fCash rates

```
# Last Implied Rate 3 Month Market
lastImpliedRate = market3Months[5] 

# Oracle Rate 3 Month Market
oracleRate = market3Months[6]
```


# nTokens

## Get nToken Address

```
nTokenAddress = notional.nTokenAddress(currencyId)
```

## Get nToken Total Supply

```
nTokenSupply = notional.nTokenTotalSupply(nTokenAddress)
```

## Get nToken PV

```
nTokenPV = notional.nTokenPresentValueUnderlyingDenominated(currencyId)
```

## Get the underlying value of one nToken

```
nTokenValue = nTokenPV / nTokenSupply
```

## Get nToken Portfolio

An nToken portfolio can hold multiple positions (Prime Cash, fCash, Liquitity tokens):

<pre><code>nTokenPrimeCashBalance = notional.getNTokenAccount(nTokenAddress)["cashBalance"]
nTokenFCashPortfolio  = notional.getNTokenPortfolio(nTokenAddress)["netfCashAssets"]
nToken3MFCashMaturity = notional.getNTokenPortfolio(nTokenAddress)["netfCashAssets"][0][1]
<strong>nToken3MFCashBalance = notional.getNTokenPortfolio(nTokenAddress)["netfCashAssets"][0][3]
</strong><strong>
</strong><strong>nTokenLiquidityTokenPortfolio = notional.getNTokenPortfolio(nTokenAddress)["liquidityTokens"]
</strong>nToken3MLiquidityTokenMaturity = notional.getNTokenPortfolio(nTokenAddress)["liquidityTokens"][0][1]
nToken3MLiquidityTokenBalance = notional.getNTokenPortfolio(nTokenAddress)["liquidityTokens"][0][3]
</code></pre>

## nToken Annual Incentive Rate

The nToken annual incentive rate defines the number of NOTE tokens that are given as incentives annually to nToken holders:

```
incentiveAnnualRate = notional.getNTokenAccount(nTokenAddress)["incentiveAnnualEmissionRate"]
```


# Leveraged Vaults

## Get Leveraged Vault Configuration Parameters

The `getVaultConfig` method can be used to get a Leverage Vault's parameters:

```
vaultConfigs = notional.getVaultConfig(vaultAddress)
vaultFeeRate = vaultConfigs["feeRate"]/1e9
liquidationRate = vaultConfigs["liquidationRate"]/1e9 - 1
reserveFeeShare = vaultConfigs["reserveFeeShare"]/100
minAccountBorrowSize = vaultConfigs["minAccountBorrowSize"]/1e8
maxRequiredAccountCollateralRatio = vaultConfigs["maxRequiredAccountCollateralRatio"]/1e9
maxDeleverageCollateralRatio = vaultConfigs["maxDeleverageCollateralRatio"]/1e9
minCollateralRatio = vaultConfigs["minCollateralRatio"]/1e9
```

## Fetch a Leveraged Vault State

The `getVaultState` method can be called to get the total amount of vault shares and debts of a given leveraged vault strategy:

```
vaultState = notional.getVaultState(accountAddress, maturityTimestamp)
totalVaultShares = vaultState["totalVaultShares"]
totalDebtUnderlying = vaultState["totalDebtUnderlying"]
```


# Oracles

## Fetch the Price Oracle Address for a given currency

The `getRateStorage` method can be used to fetch the addresses of price oracles used by the Notional protocol: &#x20;

```
# Fetch the DAI/ETH price oracle address.
DaiEthOracleAddress = notional.getRateStorage(2)["ethRate"]["rateOracle"]

# Fetch the USDC/ETH price oracle address.
UsdcEthOracleAddress = notional.getRateStorage(3)["ethRate"]["rateOracle"]
```

## ETH Price Oracle Exchange Rates

The `getCurrencyAndRates` method can be used to fetch the current ETH price oracles used to value accounts in the Notional system:&#x20;

```
# Fetch the DAI/ETH price oracle exchange rate.
notional.getCurrencyAndRates(2)["ethRate"]["rate"]/notional.getCurrencyAndRates(2)["ethRate"]["rateDecimals"]

# Fetch the USDC/ETH price oracle exchange rate.
notional.getCurrencyAndRates(3)["ethRate"]["rate"]/notional.getCurrencyAndRates(3)["ethRate"]["rateDecimals"]
```


# Governance parameters

## fCash Interest Rate Models

<pre><code># Fetch Notional's fDAI Interest Rate Models.
<strong>fCashInterestRateCurves = notional.getInterestRateCurve(1)['activeInterestRateCurve']
</strong>interestRateCurve3M = fCashInterestRateCurves[0]
interestRateCurve6M = fCashInterestRateCurves[1] 
</code></pre>

## Collateral Haircut & Buffers

```
# Fetch Notional's USDC collateral haircut.
usdcCollateralHaircut = notional.getRateStorage(3)["ethRate"]["haircut"]/100

# Fetch Notional's USDC debt buffer.
usdcDebtBuffer = notional.getRateStorage(3)["ethRate"]["buffer"]/100
```

## Liquidation Discount Parameters

```
# Fetch Notional's USDC Liquidation Discount.
notional.getRateStorage(3)["ethRate"]["liquidationDiscount"]/100 - 1
```

## fCash Risk Adjustments Parameters

```
# Fetch the fcash haircuts and debt buffers rate adjustment that are made to the oracles rates:
notional.getCashGroup(currencyId)["debtBuffer25BPS"]
notional.getCashGroup(currencyId)["fCashHaircut25BPS"]

# Fetch the fCash liquidation discounts given to fCash liquidators.
notional.getCashGroup(currencyId)["liquidationDebtBuffer25BPS"]
notional.getCashGroup(currencyId)["liquidationfCashHaircut25BPS"]

# Fetch the minimum oracle rate at which negative fCash can be discounted 
# and the maximum oracle rate at which positive fCash can be discounted.
notional.getCashGroup(currencyId)["minOracleRate25BPS"]
notional.getCashGroup(currencyId)["maxOracleRate25BPS"]

# Fetch the maximum fCash discount factor. 1 - maxDiscountFactor is the min fCash PV of positive fCash assets.
notional.getCashGroup(currencyId)["maxDiscountFactor5BPS"]
```


# Notional V3 Subgraphs

## The Graph & subgraphs&#x20;

The Graph is a decentralized protocol for indexing and querying data from blockchains. Anyone can build and publish open APIs, called subgraphs, making data easily accessible in a decentralized and reliable way. Subgraphs make it possible for anyone to query data that would otherwise be difficult to query on-chain directly. Each subgraph pays attention to events of a project’s contracts and maps that event data to data that The Graph stores in its database. Learn more about The Graph [here](https://thegraph.com/docs/en/about/introduction/).&#x20;

### GraphQL&#x20;

GraphQL is the underlying query language utilized in The Graph. GraphQL is especially useful for calls requiring lots of information where instead of making multiple API calls one only needs to do one subgraph call to get all of the information needed. Learn more about GraphQL [here](https://graphql.org/learn/).&#x20;

## Notional Subgraphs

| Version     | Network  | Subgraph Endpoint                                                                       |
| ----------- | -------- | --------------------------------------------------------------------------------------- |
| Notional V3 | Mainnet  | [Link](https://api.studio.thegraph.com/query/60626/notional-v3-mainnet/v0.0.9)          |
| Notional V3 | Arbitrum | [Link](https://api.studio.thegraph.com/query/60626/notional-v3-arbitrum/version/latest) |

## Query Notional’s subgraph with python&#x20;

To run subgraph queries through python one can use the following script and modify the url to the appropriate endpoint and modify the GQL query:

```
from gql import gql, Client from gql.transport.requests 
import RequestsHTTPTransport

#Connect with theGraph
sample_transport = RequestsHTTPTransport( url="https://api.studio.thegraph.com/proxy/33671/notional-finance-v3-arbitrum/v0.0.135/", # change to the appropriate endpoint 
verify=True, retries=10, ) client = Client( transport=sample_transport )

#Update the GQL query
query = gql('''
{
  accounts(first: 1000, where:{ systemAccountType: None}) {
    id
  }
}
''')

response = client.execute(query) 
```

We will go over a few example queries to explore Notional's V3 subgraph.


# Fetch Notional Accounts

## Get a list of account Ids

This query can be used to get a list of Notional account addresses:

```
{
  accounts(first: 1000, where:{ systemAccountType: None}) {
    id
  }
}
```

## Get an Account current positions and balances

This query can be used to get the current balances of a given Notional account:

```
{
  accounts(where:{id:"0x4e8014ff5bace498dab1a9e2b5c3f4240bc059b6"}) {
    id
    balances {
      token{symbol}
      snapshots(first:1, orderBy:blockNumber, orderDirection:desc) {
        currentBalance
      }
    }
  }
}
```


# Fetch Notional's reserves

## Get Notional's Reserve balances

This query can be used to fetch the protocol's Prime Cash reserves:

```
{
  accounts(where:{ systemAccountType: FeeReserve}) {
    id
    balances {
      token{symbol}
      snapshots(first:1, orderBy:blockNumber, orderDirection:desc) {
        currentBalance
      }
    }
  }
}
```


# Fetch Notional nToken accounts

## Get Notional's nToken accounts balances

This query can be used to fetch nToken accounts positions:&#x20;

```
{
  accounts(where:{ systemAccountType: nToken}) {
    id
    balances {
      token{symbol}
      snapshots(first:1, orderBy:blockNumber, orderDirection:desc) {
        currentBalance
      }
    }
  }
}
```


# Fetch Historical Trades

## Get all fCash historical trades

This query can be used to fetch historical fCash trades. This includes fCash trades occurring upon nToken redemptions and nToken mints above the leverage threshold.

```
{
  transferBundles(orderBy:timestamp, where:{bundleName_in:["Buy fCash","Sell fCash"], transfers_:{tokenType:"fCash"}}){
    bundleName
    timestamp
    transfers{
      from{id}
      to{id}
      token{symbol}
      value
      valueInUnderlying
    }
  }
}
```


# Fetch an Account's P\&L

## Fetch the historical P\&L of a given account

This query can be used to fetch the historical per position P\&L of a Notional user:

```
{
  accounts(where:{id: "0x4e8014ff5bace498dab1a9e2b5c3f4240bc059b6"}) {
    id
    balances {
      id
      token { symbol } 
      snapshots(orderBy:blockNumber, orderDirection:desc) {
        id
        currentBalance
        _accumulatedBalance
        _accumulatedCostRealized
        _accumulatedCostAdjustedBasis
        adjustedCostBasis
        currentProfitAndLossAtSnapshot
        totalILAndFeesAtSnapshot
        totalProfitAndLossAtSnapshot
        totalInterestAccrualAtSnapshot
        profitLossLineItems {
          id
          tokenAmount
          bundle {bundleName}
          underlyingAmountRealized
          underlyingAmountSpot
          realizedPrice
          spotPrice
        }
      }
    }
  }
}
```


# Fetch current fCash and Prime Cash Rates

## Get current Prime Cash lending rates

This query can be used to get current Prime Cash variable lending rates:

```
{
  oracles(where:{oracleType: "PrimeCashSpotInterestRate"}){
    base{symbol}
    latestRate
  }
}
```

## Get current Prime Cash borrowing rates

This query can be used to get current Prime Cash variable borrowing rates:

```
{
  oracles(where:{oracleType: "PrimeDebtSpotInterestRate"}){
    base{symbol}
    latestRate
  }
}
```

## Get current fCash rates

This query can be used to get current fCash fixed last implied rates:

```
{
  oracles(where:{oracleType: "fCashSpotRate"}){
    base{
      symbol
    }
    quote{
      symbol
      maturity
    }
    latestRate
  }
}
```


# Fetch Historical Prime Cash & Prime Debt Exchange Rates

## Get Prime Cash to Underlying exchange rates

This query can be used to fetch the underlying exchange rate between Prime Cash and the underlying currency:

```
{
primeCashMarkets{
  snapshots(orderBy: timestamp, orderDirection:desc){
    market{
      id
    }
    timestamp
    underlyingScalar
    supplyScalar
  }
  }
}
```

## Get Prime Debt to Underlying exchange rates

This query can be used to fetch the underlying exchange rate between Prime Debts and the underlying currency:

```
{
primeCashMarkets{
  snapshots(orderBy: timestamp, orderDirection:desc){
    market{
      id
    }
    timestamp
    underlyingScalar
    debtScalar
  }
  }
}
```


# Fetch Prime Cash Market Balances

## Get Prime Cash Market Balances

This query can be used to fetch Prime Cash market balances and a Prime Cash markets total debt outstanding: &#x20;

```
{
primeCashMarkets{
  snapshots(first: 1, orderBy: timestamp, orderDirection:desc){
    market{
      id
    }
    timestamp
    underlyingScalar
    supplyScalar
    debtScalar
    totalUnderlyingHeld
    totalPrimeCashInUnderlying
    totalPrimeDebtInUnderlying
    totalPrimeCash
    totalPrimeDebt
  }
  }
}
```


# Fetch fCash Market Balances

## Get fCash Market balances

This query can be used to fetch fCash market total balances and a fCash markets total debt outstanding: &#x20;

```
{
  fCashMarkets{
    snapshots(first: 1, orderBy: timestamp, orderDirection:desc){
    market{id}
    totalPrimeCash
    totalfCash
    totalPrimeCashInUnderlying
    totalfCashPresentValue
    totalfCashDebtOutstanding
    totalfCashDebtOutstandingPresentValue
    }
  }
}
```


# Fetch Outstanding Debt

## Get Prime Cash and fCash Markets Outstanding Debts

This query can be used to fetch Notional outstanding variable and fixed debts:&#x20;

```
{
primeCashMarkets{
  snapshots(first: 1, orderBy: timestamp, orderDirection:desc){
    market{id}
    totalPrimeDebtInUnderlying
  }
  }
  fCashMarkets{
    snapshots(first: 1, orderBy: timestamp, orderDirection:desc){
    market{id}
    totalfCashDebtOutstandingPresentValue
  }
  }
}
```


# Fetch Historical nToken Exchange Rates

## Get nToken to underlying historical exchange rates&#x20;

This query can be used to get the historical exchange rates between an underlying currency and an nToken PV:

```
{
oracles(where:{oracleType:"nTokenToUnderlyingExchangeRate"}){
  base{symbol}
  latestRate
}
}
```


# Fetch ETH Oracle Exchange Rates

## Get Historical Price Oracle Exchange Rates&#x20;

This query can be used to get historical Chainlink oracle prices for all listed base currencies:

```
{
oracles(where:{oracleType:"Chainlink"}){
  base{symbol}
  quote{symbol}
  latestRate
}
}
```


# Fetch Annual Incentive Rates

## Get nToken Annual NOTE Incentive Rates

This query can be used to fetch the annual NOTE incentive rates for all nTokens:  &#x20;

```
{
  currencyConfigurations{
    underlying{symbol}
    incentiveEmissionRate
  }
}
```


# Fetch Interest Rate Models

## Get Prime Cash and fCash Interest Rate Models

This query can be used to fetch Prime Cash and fCash interest rate models. Ids reference the currency, the market index and if the model is the current Interest rate model or the next interest rate model. For example, the id "3:0:current" identifies the Prime Cash Market for currency id 3 (USDC). Id "6:2:current" identifies the 6 month fCash market (market index = 2) interest rate model for currency id 6 (FRAX).

```
{
interestRateCurves{
  id
  kinkRate1
  kinkRate2
  kinkUtilization1
  kinkUtilization2
  maxRate
  maxFeeRate
  minFeeRate
  feeRatePercent
}
}
```


# Fetch Governance Parameters

## Get Governance Parameters and Configurations&#x20;

This query can be used to fetch Notional's governance parameters per currency:

```
{
  currencyConfigurations {
    underlying {
      symbol
    }
    collateralHaircut
    debtBuffer
    proportions
    depositShares
    residualPurchaseTimeBufferSeconds
    residualPurchaseIncentiveBasisPoints
    fCashMinOracleRate
    fCashMaxOracleRate
    fCashMaxDiscountFactor
    fCashHaircutBasisPoints
    fCashDebtBufferBasisPoints
    fCashReserveFeeSharePercent
    fCashRateOracleTimeWindowSeconds
    fCashLiquidationDebtBufferBasisPoints
    pvHaircutPercentage
    primeDebtAllowed
    leverageThresholds
    rebalancingTargets
    rebalancingCooldown
    liquidationDiscount
    liquidationHaircutPercentage
    maxUnderlyingSupply
    primeCashRateOracleTimeWindowSeconds
    treasuryReserveBuffer
  }
}
```


