-
Notifications
You must be signed in to change notification settings - Fork 111
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Taylor Brent <[email protected]>
- Loading branch information
1 parent
cda7d8a
commit c727c40
Showing
41 changed files
with
601 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# SUSDS SSR Collateral Plugin | ||
|
||
## Summary | ||
|
||
This plugin allows `sUSDS` (Sky) holders to use their tokens as collateral in the Reserve Protocol. | ||
|
||
`sUSDS` token represents a tokenized implementation of the Sky Savings Rate for `USDS`, fully compliant with the ERC-4626 standard. It enables real-time share-to-asset conversions, ensuring accurate values even if the system's drip function hasn't been called recently. | ||
|
||
These `sUSDS` tokens serve as a digital record of any value accrued to a specific position. The Sky Protocol dynamically and automatically adds USDS tokens to the entire pool of USDS supplied to the module every few seconds, in accordance with the Sky Savings Rate. As a result of the tokens auto-accumulating in the pool over time, the value tends to accrue within the sUSDS being held. | ||
|
||
Since it is ERC4626, the redeemable USDS amount can be gotten by dividing `sUSDS.totalAssets()` by `sUSDS.totalSupply()`. | ||
`sUSDS` contract: <https://etherscan.io/address/0xdC035D45d973E3EC169d2276DDab16f1e407384F#code> | ||
|
||
Sky Money: https://sky.money/ | ||
|
||
## Implementation | ||
|
||
### Units | ||
|
||
| tok | ref | target | UoA | | ||
| ----- | ---- | ------ | --- | | ||
| sUSDS | USDS | USD | USD | | ||
|
||
### Functions | ||
|
||
#### refPerTok {ref/tok} | ||
|
||
`return shiftl_toFix(IERC4626(address(erc20)).convertToAssets(oneShare), -refDecimals, FLOOR);` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// SPDX-License-Identifier: BlueOak-1.0.0 | ||
pragma solidity 0.8.19; | ||
|
||
import "../ERC4626FiatCollateral.sol"; | ||
|
||
/** | ||
* @title SUSDS Collateral | ||
* @notice Collateral plugin for the SSR wrapper sUSDS | ||
* tok = SUSDS (transferrable SSR-locked USDS) | ||
* ref = USDS | ||
* tar = USD | ||
* UoA = USD | ||
*/ | ||
contract SUSDSCollateral is ERC4626FiatCollateral { | ||
/// @param config.chainlinkFeed {UoA/ref} price of USDS in USD terms | ||
constructor(CollateralConfig memory config, uint192 revenueHiding) | ||
ERC4626FiatCollateral(config, revenueHiding) | ||
{ | ||
require(config.defaultThreshold != 0, "defaultThreshold zero"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// SPDX-License-Identifier: BlueOak-1.0.0 | ||
pragma solidity 0.8.19; | ||
|
||
interface ISUsds { | ||
function vow() external view returns (address); | ||
|
||
function usdsJoin() external view returns (address); | ||
|
||
function usds() external view returns (address); | ||
|
||
function ssr() external view returns (uint256); | ||
|
||
function chi() external view returns (uint192); | ||
|
||
function rho() external view returns (uint64); | ||
|
||
function drip() external returns (uint256); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
// SPDX-License-Identifier: BlueOak-1.0.0 | ||
pragma solidity 0.8.19; | ||
|
||
interface VatLike { | ||
function hope(address) external; | ||
|
||
function suck( | ||
address, | ||
address, | ||
uint256 | ||
) external; | ||
} | ||
|
||
interface UsdsJoinLike { | ||
function vat() external view returns (address); | ||
|
||
function usds() external view returns (address); | ||
|
||
function exit(address, uint256) external; | ||
} | ||
|
||
interface UsdsLike { | ||
function transfer(address, uint256) external; | ||
|
||
function transferFrom( | ||
address, | ||
address, | ||
uint256 | ||
) external; | ||
} | ||
|
||
contract SUsdsMock { | ||
// --- Storage Variables --- | ||
|
||
// Admin | ||
mapping(address => uint256) public wards; | ||
// ERC20 | ||
uint256 public totalSupply; | ||
mapping(address => uint256) public balanceOf; | ||
mapping(address => mapping(address => uint256)) public allowance; | ||
mapping(address => uint256) public nonces; | ||
// Savings yield | ||
uint192 public chi; // The Rate Accumulator [ray] | ||
uint64 public rho; // Time of last drip [unix epoch time] | ||
uint256 public ssr; // The USDS Savings Rate [ray] | ||
|
||
// --- Constants --- | ||
|
||
// ERC20 | ||
string public constant name = "Savings USDS"; | ||
string public constant symbol = "sUSDS"; | ||
string public constant version = "1"; | ||
uint8 public constant decimals = 18; | ||
// Math | ||
uint256 private constant RAY = 10**27; | ||
|
||
// --- Immutables --- | ||
|
||
// EIP712 | ||
bytes32 public constant PERMIT_TYPEHASH = | ||
keccak256( | ||
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" | ||
); | ||
// Savings yield | ||
UsdsJoinLike public immutable usdsJoin; | ||
VatLike public immutable vat; | ||
UsdsLike public immutable usds; | ||
address public immutable vow; | ||
|
||
constructor(address usdsJoin_, address vow_) { | ||
usdsJoin = UsdsJoinLike(usdsJoin_); | ||
vat = VatLike(UsdsJoinLike(usdsJoin_).vat()); | ||
usds = UsdsLike(UsdsJoinLike(usdsJoin_).usds()); | ||
vow = vow_; | ||
|
||
chi = uint192(RAY); | ||
rho = uint64(block.timestamp); | ||
ssr = RAY; | ||
vat.hope(address(usdsJoin)); | ||
wards[msg.sender] = 1; | ||
} | ||
|
||
// Mock function to be able to override chi in tests | ||
function setChi(uint192 newValue) external { | ||
chi = newValue; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
85 changes: 85 additions & 0 deletions
85
scripts/deployment/phase2-assets/collaterals/deploy_sky_susds.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import fs from 'fs' | ||
import hre from 'hardhat' | ||
import { getChainId } from '../../../../common/blockchain-utils' | ||
import { networkConfig } from '../../../../common/configuration' | ||
import { bn, fp } from '../../../../common/numbers' | ||
import { expect } from 'chai' | ||
import { CollateralStatus } from '../../../../common/constants' | ||
import { | ||
getDeploymentFile, | ||
getAssetCollDeploymentFilename, | ||
IAssetCollDeployments, | ||
getDeploymentFilename, | ||
fileExists, | ||
} from '../../common' | ||
import { priceTimeout } from '../../utils' | ||
import { SUSDSCollateral } from '../../../../typechain' | ||
import { ContractFactory } from 'ethers' | ||
import { ORACLE_ERROR, ORACLE_TIMEOUT } from '#/test/plugins/individual-collateral/sky/constants' | ||
|
||
async function main() { | ||
// ==== Read Configuration ==== | ||
const [deployer] = await hre.ethers.getSigners() | ||
|
||
const chainId = await getChainId(hre) | ||
|
||
console.log(`Deploying Collateral to network ${hre.network.name} (${chainId}) | ||
with burner account: ${deployer.address}`) | ||
|
||
if (!networkConfig[chainId]) { | ||
throw new Error(`Missing network configuration for ${hre.network.name}`) | ||
} | ||
|
||
// Get phase1 deployment | ||
const phase1File = getDeploymentFilename(chainId) | ||
if (!fileExists(phase1File)) { | ||
throw new Error(`${phase1File} doesn't exist yet. Run phase 1`) | ||
} | ||
// Check previous step completed | ||
const assetCollDeploymentFilename = getAssetCollDeploymentFilename(chainId) | ||
const assetCollDeployments = <IAssetCollDeployments>getDeploymentFile(assetCollDeploymentFilename) | ||
|
||
const deployedCollateral: string[] = [] | ||
|
||
/******** Deploy SUSDS Collateral - sUSDS **************************/ | ||
|
||
const SUSDSCollateralFactory: ContractFactory = await hre.ethers.getContractFactory( | ||
'SUSDSCollateral' | ||
) | ||
|
||
const collateral = <SUSDSCollateral>await SUSDSCollateralFactory.connect(deployer).deploy( | ||
{ | ||
priceTimeout: priceTimeout.toString(), | ||
chainlinkFeed: networkConfig[chainId].chainlinkFeeds.USDS, | ||
oracleError: ORACLE_ERROR.toString(), // 0.3% | ||
erc20: networkConfig[chainId].tokens.sUSDS, | ||
maxTradeVolume: fp('1e6').toString(), // $1m, | ||
oracleTimeout: ORACLE_TIMEOUT.toString(), // 24h | ||
targetName: hre.ethers.utils.formatBytes32String('USD'), | ||
defaultThreshold: ORACLE_ERROR.add(fp('0.01')).toString(), // 1.3% | ||
delayUntilDefault: bn('86400').toString(), // 24h | ||
}, | ||
bn(0) | ||
) | ||
await collateral.deployed() | ||
|
||
console.log(`Deployed sUSDS to ${hre.network.name} (${chainId}): ${collateral.address}`) | ||
|
||
await (await collateral.refresh()).wait() | ||
expect(await collateral.status()).to.equal(CollateralStatus.SOUND) | ||
|
||
assetCollDeployments.collateral.sUSDS = collateral.address | ||
assetCollDeployments.erc20s.sUSDS = networkConfig[chainId].tokens.sUSDS | ||
deployedCollateral.push(collateral.address.toString()) | ||
|
||
fs.writeFileSync(assetCollDeploymentFilename, JSON.stringify(assetCollDeployments, null, 2)) | ||
|
||
console.log(`Deployed collateral to ${hre.network.name} (${chainId}) | ||
New deployments: ${deployedCollateral} | ||
Deployment file: ${assetCollDeploymentFilename}`) | ||
} | ||
|
||
main().catch((error) => { | ||
console.error(error) | ||
process.exitCode = 1 | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import hre from 'hardhat' | ||
import { getChainId } from '../../../common/blockchain-utils' | ||
import { developmentChains, networkConfig } from '../../../common/configuration' | ||
import { fp, bn } from '../../../common/numbers' | ||
import { | ||
getDeploymentFile, | ||
getAssetCollDeploymentFilename, | ||
IAssetCollDeployments, | ||
} from '../../deployment/common' | ||
import { priceTimeout, verifyContract } from '../../deployment/utils' | ||
import { | ||
ORACLE_ERROR, | ||
ORACLE_TIMEOUT, | ||
} from '../../../test/plugins/individual-collateral/sky/constants' | ||
|
||
let deployments: IAssetCollDeployments | ||
|
||
async function main() { | ||
// ********** Read config ********** | ||
const chainId = await getChainId(hre) | ||
if (!networkConfig[chainId]) { | ||
throw new Error(`Missing network configuration for ${hre.network.name}`) | ||
} | ||
|
||
if (developmentChains.includes(hre.network.name)) { | ||
throw new Error(`Cannot verify contracts for development chain ${hre.network.name}`) | ||
} | ||
|
||
const assetCollDeploymentFilename = getAssetCollDeploymentFilename(chainId) | ||
deployments = <IAssetCollDeployments>getDeploymentFile(assetCollDeploymentFilename) | ||
|
||
/******** Verify sUSDS **************************/ | ||
await verifyContract( | ||
chainId, | ||
deployments.collateral.sUSDS, | ||
[ | ||
{ | ||
priceTimeout: priceTimeout.toString(), | ||
chainlinkFeed: networkConfig[chainId].chainlinkFeeds.USDS, | ||
oracleError: ORACLE_ERROR.toString(), // 0.3% | ||
erc20: networkConfig[chainId].tokens.sUSDS, | ||
maxTradeVolume: fp('1e6').toString(), // $1m, | ||
oracleTimeout: ORACLE_TIMEOUT.toString(), // 24h | ||
targetName: hre.ethers.utils.formatBytes32String('USD'), | ||
defaultThreshold: ORACLE_ERROR.add(fp('0.01')).toString(), // 1.3% | ||
delayUntilDefault: bn('86400').toString(), // 24h | ||
}, | ||
bn(0), | ||
], | ||
'contracts/plugins/assets/sky/SUSDSCollateral.sol:SUSDSCollateral' | ||
) | ||
} | ||
|
||
main().catch((error) => { | ||
console.error(error) | ||
process.exitCode = 1 | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.