This repository contains the core smart contract code for Open Dollar.
Documentation
- Technical Contracts docs: https://contracts.opendollar.com
- Protocol Docs: https://docs.opendollar.com
Contract Deployments
Addresses for can be found in the app: https://app.opendollar.com/stats
Tools
@opendollar/abis
- ABI interfaces are published automatically from this repo, on merge tomain
https://www.npmjs.com/package/@opendollar/abis@opendollar/sdk
- Library to interact with Open Dollar smart contracts https://github.com/open-dollar/od-sdk
Audit | Date | Auditor | Commit | Changes Since Audit | Report |
---|---|---|---|---|---|
contracts | October, 2023 | Cod4rena | f401eb5 | View Changes | View Report |
app | March, 2024 | Quantstamp | 7c9b18c | View Changes | View Report |
contracts | April, 2024 | Quantstamp | 6cdc848 | View Changes | View Report |
relayer | April, 2024 | Pashov Audit Group | 453222d | View Changes | View Report |
A Security Scan was performed by Pessimistic April, 2024 at a0b7640. (Report to be published)
Additional audits completed prior to forking this codebase can be found here: https://github.com/hai-on-op/audit-reports
Run:
yarn install
,
yarn build
,
yarn test
When running forge
, you can specify the profile to use using the FOUNDRY_PROFILE environment variable. e.g. export FOUNDRY_PROFILE=test && forge test
. Alternatively, you can add FOUNDRY_PROFILE=test
to .env
and run source .env
.
Start Anvil:
anvil
Next, copy the private key from anvil terminal output into your .env
ANVIL_RPC=http://127.0.0.1:8545
ANVIL_ONE=0x....
Deploy the contracts locally:
yarn deploy:anvil
You now have a local anvil test environment with a locally deployed and instantiated version of the Open Dollar Protocol.
NOTE: You may need to manually verify that all required addresses were updated in
AnvilContracts.t.sol
. The scriptparseAnvilDeployments.js
is not perfect.
The following scripts are used to simulate various states of the protocol. The scripts can be found in script/states
and are described below:
DebtState.s.sol
DebtState.s.sol
puts every SAFE in jeopardy of liquidation by driving the non-wstETH collateral prices down. After running DebtState any SAFEs can be liquidated freely for testing.
forge script script/states/DebtState.s.sol:DebtState --fork-url http://localhost:8545 -vvvvv
LiquidationAuction.s.sol
LiquidationAuction.s.sol
takes DebtState a step further and liquidates every SAFE on the platform. It then initiates and completes a single collateral auction. We also create a chunk of unbacked debt in the accounting engine which enables launching a debt auction. This state can be used to test liquidations, launching collateral auctions, launching a debt auction or viewing a completed collateral auction.
forge script script/states/DebtAuction.s.sol:DebtAuction --fork-url http://localhost:8545 -vvvvv
DebtAuction.s.sol
DebtAuction.s.sol
takes LiquidationAuction a step further and creates a large amount of unbacked debt in the
AccountingEngine; which allows us to then create a debt auction. The debt auction is then bid on and settled. This
allows testing of viewing a completed debt auction.
forge script script/states/DebtAuction.s.sol:DebtAuction --fork-url http://localhost:8545 -vvvvv`
SurplusState.s.sol
SurplusState.s.sol
pushes the clock forward so that the protocol accrues surplus. It can be used to test launching a
SurplusAuction.
forge script script/states/SurplusState.s.sol:SurplusState --fork-url http://localhost:8545 -vvvvv
SurplusAuction.s.sol
SurplusAuction.s.sol
takes SurplusState a step farther, and initiates a surplus auction, bids on it and settles it.
It can be used to test viewing a completed surplus auction.`
forge script script/states/SurplusAuction.s.sol:SurplusAuction --fork-url http://localhost:8545 -vvvvv
yarn test
will run all tests in the test folder. These tests are pranked on a fork Arbitrum mainnet. Additionally, there are Sepolia deployment tests.
Coverage testing is performed using lcov and a local Anvil fork of the contracts. First install lcov for mac/linx.
-
Start Anvil using the instructions above.
-
To generate a report, run the command:
yarn test:coverage
- Open
coverage-report/index.html
to view the report.
OpenDollar governance follows the common pattern of:
- generating a governance proposal
- submitting a governance proposal
- queuing the governance proposal
- executing the governance proposal
We include a set of governance scripts in script/gov
which allow DAO members to propose, queue and execute different governance actions.
yarn propose [action flag] [option flag] [path to input json]
All available flags can also be viewed with
yarn propose --help
The input for the proposal is a json file in the "gov-inputs/[network]" folder. You can find basic templates in these folders.
All JSON inputs have these required fields:
chainid
: the chainId of the desired network.network
: the desired network to be submitted on.proposalType
: the type of proposal. This must be in camel case with the first letter capitalized e.g. "AddCollateral"ODGovernor_Address
: the address of the OD_Governor. if you don't want to enter this manually use the--auto
flag.description
: a description of the proposal being made.
Contract addresses with the "_Address" suffix can be automatically added by the generation script with the --auto
flag.
For example:
yarn propose -g --auto /gov-input/anvil/new-AddCollateral.json
will fill inProtocolToken_Address, ODGovernor_Address, SAFEEngine_Address, OracleRelayer_Address, LiquidationEngine_Address, TaxCollector_Address, GlobalSettlement_Address
from script/anvil/deployment/AnvilContracts.t.sol
The output is always a JSON file which includes at least the following proposalParams
:
{
"proposalId": uint256,
"targets": address[],
"values": uint256[]
"calldatas": bytes[],
"description": string,
"descriptionHash": bytes32
}
The JSON output may also include extra params for informative purposes and for execution params for the scripts themselves. Please do not alter the generated outputs in any way. This will invalidate the proposal.
- Fill in necessarry data in the input Json template.
- Generate the Proposal with
yarn propose -g --auto /gov-input/new-ProposalType.json
- If you haven't delegated your tokens you can delegate to yourself with
yarn propose -d /gov-output/11111111-proposalType.json
- Commit and push your changes so someone else can use the generate script to with the same params to verify the output is correct.
- After Verification, Submit the proposal with
yarn propose -s /gov-output/11111111-proposalType.json
- Vote on a proposal with
yarn propose -v /gov-output/11111111-proposalType.json
- Queue a proposal with
yarn propose -q /gov-output/11111111-proposalType.json
- Execute a proposal with
yarn propose -x /gov-output/11111111-proposalType.json
note:
If you want to use the --delegate
flag to delegate your tokens, you must add the ProtocolToken_Address
field to the input json, or use the --auto
flag when generating the proposal.
Add a new ERC20 as collateral to the system.
Template: new-AddCollateral.json
Required json fields
- newCollateralAddress: the token address of the proposed collateral to be added.
- newCollateralType: the symbol of the collateral token e.g. ARB
- SAFEEngineCollateralParams:
- collateralDebtCeiling: RAD, The maximum amount of debt that can be generated with the collateral type
- collateralDebtFloor: RAD, The minimum amount of debt that must be generated by a SAFE using the collateral
- TaxCollectorCollateralParams:
- stabilityFee: RAY, the per collateral stability fee.
- LiquidationEngineCollateralParams:
- newCAHChild: This will be automatically added in the generation script. you can leave this empty.
- liquidationPenalty: WAD, Penalty applied to every liquidation involving this collateral type.
- liquidationQuantity: RAD, Max amount of system coins to request in one auction for this collateral type.
- OracleRelayerCollateralParams:
- delayedOracle: Usually a DelayedOracle that enforces delays to fresh price feeds.
- safetyCRatio: RAY, CRatio used to compute the 'safePrice' - the price used when generating debt in SAFEEngine.
- liquidationCRatio: RAY, CRatio used to compute the 'liquidationPrice' the price used when liquidating SAFEs.
- CollateralAuctionHouseParams:
- maximumDiscount: WAD, Maximum discount at which collateral is being sold
- minimumBid: WAD, Minimum acceptable bid
- minimumDiscount: WAD, Minimum discount at which collateral is being sold
- perSecondDiscountUpdateRate: RAY, Rate at which the discount will be updated in an auction. This script proposes adding a new collateral to the system (deploys new contracts via the collateral join, collateral auction house factories and it adds the correct authorizations to the needed contracts).
Modify any parameters in a Modifiable.sol
contract.
Template: new-ModifyParameters.json
Required JSON vars:
objectArray
: each object in the array can be a param to be modified. Each object must contain:target
: the address of the target contract.param
: the name of the param to be modified.type
: the data type of the input data.data
: the input data. this can be a string, uint or an address. depending on the requirement of the parameter that is being modified.
Update the redemption rate PI controller.
Template: new-UpdatePIDController.json
To update the PI controller you simply make a ModifyParameters proposal with all the PI controller params you would like to modify listed as individual params in the objectArray
.
NOTE: see
IPIDController.sol
for more information about this.
Transfer ERC20 tokens from the TimelockController or any target contract.
Template: newERC20Transfer.json
You can propose multiple transfers in the same proposal by adding multiple transfer objects to the objectArray
Required json vars:
objectArray
: each object in the objectArray is a proposed transfer.erc20Token
: the address of the token to be transferedtransferTo
: the address of the token recipientamount
: the amount to be transfered in wei.
Add rewards to the Camelot Nitro pool