If you notice some outdated information please let us know!
PASS
The final review score is indicated as a percentage. The percentage is calculated as Achieved Points due to MAX Possible Points. For each element the answer can be either Yes/No or a percentage. For a detailed breakdown of the individual weights of each question, please consult this document.
Very simply, the audit looks for the following declarations from the developer's site. With these declarations, it is reasonable to trust the smart contracts.
This report is for informational purposes only and does not constitute investment advice of any kind, nor does it constitute an offer to provide investment advisory or other services. Nothing in this report shall be considered a solicitation or offer to buy or sell any security, token, future, option or other financial instrument or to offer or provide any investment advice or service to any person in any jurisdiction. Nothing contained in this report constitutes investment advice or offers any opinion with respect to the suitability of any security, and the views expressed in this report should not be taken as advice to buy, sell or hold any security. The information in this report should not be relied upon for the purpose of investing. In preparing the information contained in this report, we have not taken into account the investment needs, objectives and financial circumstances of any particular investor. This information has no regard to the specific investment objectives, financial situation and particular needs of any specific recipient of this information and investments discussed may not be suitable for all investors.
Any views expressed in this report by us were prepared based upon the information available to us at the time such views were written. The views expressed within this report are limited to DeFiSafety and the author and do not reflect those of any additional or third party and are strictly based upon DeFiSafety, its authors, interpretations and evaluation of relevant data. Changed or additional information could cause such views to change. All information is subject to possible correction. Information may quickly become unreliable for various reasons, including changes in market conditions or economic circumstances.
This completed report is copyright (c) DeFiSafety 2023. Permission is given to copy in whole, retaining this copyright label.
This section looks at the code deployed on the relevant chain that gets reviewed and its corresponding software repository. The document explaining these questions is here.
1. Are the smart contract addresses easy to find? (%)
They can be found at https://docs.ousd.com/smart-contracts/registry , as indicated in the Appendix.
2. How active is the primary contract? (%)
Contract Vault is used less than 10 times a day, as indicated in the Appendix. Nevertheless, more than 10 instances of OUSD per day are being transacted with, meaning we will grant a marginally higher score in this instance.
3. Does the protocol have a public software repository? (Y/N)
4. Is there a development history visible? (%)
At 2887 commits, this protocol clearly pays due respect to its origin story.
5. Is the team public (not anonymous)?
The team is easily located.
The difference between this and the old link is solely the link. This section looks at the software documentation. The document explaining these questions is here.
6. Is there a whitepaper? (Y/N)
Location: https://docs.ousd.com
7. Is the protocol's software architecture documented? (Y/N)
This protocol's software architecture is documented.
8. Does the software documentation fully cover the deployed contracts' source code? (%)
There are only API functions documented in Origin's documentation.
9. Is it possible to trace the documented software to its implementation in the protocol's source code? (%)
Origin's documentation only lists the API functions and describes them.
10. Has the protocol tested their deployed code? (%)
Code examples are in the Appendix at the end of this report.. As per the SLOC, there is 246% testing to code (TtC). This score is guided by the Test to Code ratio (TtC). Generally a good test to code ratio is over 100%. However, the reviewer's best judgement is the final deciding factor.
11. How covered is the protocol's code? (%)
A code coverage testing report was documented. Code coverage sits at 86.685%.
12. Does the protocol provide scripts and instructions to run their tests? (Y/N)
Scripts/Instructions location: https://github.com/originprotocol/origin-dollar#installation
13. Is there a detailed report of the protocol's test results?(%)
This protocol documents yarn test script reports with each push request.
14. Has the protocol undergone Formal Verification? (Y/N)
This protocol has undergone formal verification on the token contract. The rest of the protocol was not in scope for Certora's review.
15. Were the smart contracts deployed to a testnet? (Y/N)
This protocol has been deployed to a testnet.
This section looks at the 3rd party software audits done. It is explained in this document.
16. Is the protocol sufficiently audited? (%)
OUSD has been audited multiple times, though each was post-launch. This protocol will not be repeating this mistake: > Developers deploying untested contracts before essential security audits have been completed need to be more comprehensive and diligent when developing their strapiucts. This is commendable. Many protocols do not learn from this mistake.
17. Is the bounty value acceptably high (%)
This protocol offers an active bug bounty of $250K
This section covers the documentation of special access controls for a DeFi protocol. The admin access controls are the contracts that allow updating contracts or coefficients in the protocol. Since these contracts can allow the protocol admins to "change the rules", complete disclosure of capabilities is vital for user's transparency. It is explained in this document.
18. Is the protocol's admin control information easy to find?
Admin control information was well documented at this location. This was quick to find.
19. Are relevant contracts clearly labelled as upgradeable or immutable? (%)
The relevant contracts are identified as upgradeable, as identified here.
20. Is the type of smart contract ownership clearly indicated? (%)
Ownership is clearly indicated in this location.
21. Are the protocol's smart contract change capabilities described? (%)
Some smart contract change capabilities are identified, but definitely not all of them.
22. Is the protocol's admin control information easy to understand? (%)
This information is in clear language and relates to user fund safety.
23. Is there sufficient Pause Control documentation? (%)
This protocol's pause control functions are documented and briefly summarized at https://docs.ousd.com/governance/admin-privileges#strategist.
24. Is there sufficient Timelock documentation? (%)
This protocol has good timelock documentation which can be found at this location.
25. Is the Timelock of an adequate length? (Y/N)
The timelock is of a relevant length, as specified in this location.
This section goes over the documentation that a protocol may or may not supply about their Oracle usage. Oracles are a fundamental part of DeFi as they are responsible for relaying tons of price data information to thousands of protocols using blockchain technology. Not only are they important for price feeds, but they are also an essential component of transaction verification and security. This is explained in this document.
26. Is the protocol's Oracle sufficiently documented? (%)
The protocol's oracle source is partially documented at this location. The contracts dependent are identified. There is no relevant software function documentation, but the deltas of each price source are clearly outlined.
27. Is front running mitigated by this protocol? (Y/N)
This protocol documents front running mitigation techniques.
28. Can flashloan attacks be applied to the protocol, and if so, are those flashloan attack risks mitigated? (Y/N)
This protocol documents flashloan countermeasures at this location. It has implemented Chainlink. This could be stated explicitly to reassure users.
1// SPDX-License-Identifier: agpl-3.0
2pragma solidity ^0.8.0;
3
4/**
5 * @title OUSD Timelock Contract
6 * @author Origin Protocol Inc
7 */
8import "@openzeppelin/contracts/utils/math/SafeMath.sol";
9
10interface CapitalPausable {
11 function pauseCapital() external;
12
13 function unpauseCapital() external;
14}
15
16contract Timelock {
17 using SafeMath for uint256;
18
19 event NewAdmin(address indexed newAdmin);
20 event NewPendingAdmin(address indexed newPendingAdmin);
21 event NewDelay(uint256 indexed newDelay);
22 event CancelTransaction(
23 bytes32 indexed txHash,
24 address indexed target,
25 string signature,
26 bytes data,
27 uint256 eta
28 );
29 event ExecuteTransaction(
30 bytes32 indexed txHash,
31 address indexed target,
32 string signature,
33 bytes data,
34 uint256 eta
35 );
36 event QueueTransaction(
37 bytes32 indexed txHash,
38 address indexed target,
39 string signature,
40 bytes data,
41 uint256 eta
42 );
43
44 uint256 public constant GRACE_PERIOD = 3 days;
45 uint256 public constant MINIMUM_DELAY = 1 minutes;
46 uint256 public constant MAXIMUM_DELAY = 2 days;
47
48 address public admin;
49 address public pendingAdmin;
50 uint256 public delay;
51
52 mapping(bytes32 => bool) public queuedTransactions;
53
54 /**
55 * @dev Throws if called by any account other than the Admin.
56 */
57 modifier onlyAdmin() {
58 require(msg.sender == admin, "Caller is not the admin");
59 _;
60 }
61
62 constructor(address admin_, uint256 delay_) {
63 require(
64 delay_ >= MINIMUM_DELAY,
65 "Timelock::constructor: Delay must exceed minimum delay."
66 );
67 require(
68 delay_ <= MAXIMUM_DELAY,
69 "Timelock::setDelay: Delay must not exceed maximum delay."
70 );
71
72 admin = admin_;
73 delay = delay_;
74 }
75
76 function setDelay(uint256 delay_) public {
77 require(
78 msg.sender == address(this),
79 "Timelock::setDelay: Call must come from Timelock."
80 );
81 require(
82 delay_ >= MINIMUM_DELAY,
83 "Timelock::setDelay: Delay must exceed minimum delay."
84 );
85 require(
86 delay_ <= MAXIMUM_DELAY,
87 "Timelock::setDelay: Delay must not exceed maximum delay."
88 );
89 delay = delay_;
90
91 emit NewDelay(delay);
92 }
93
94 function acceptAdmin() public {
95 require(
96 msg.sender == pendingAdmin,
97 "Timelock::acceptAdmin: Call must come from pendingAdmin."
98 );
99 admin = msg.sender;
100 pendingAdmin = address(0);
101
102 emit NewAdmin(admin);
103 }
104
105 function setPendingAdmin(address pendingAdmin_) public onlyAdmin {
106 pendingAdmin = pendingAdmin_;
107
108 emit NewPendingAdmin(pendingAdmin);
109 }
110
111 function queueTransaction(
112 address target,
113 string memory signature,
114 bytes memory data,
115 uint256 eta
116 ) internal returns (bytes32) {
117 require(
118 msg.sender == admin,
119 "Timelock::queueTransaction: Call must come from admin."
120 );
121 require(
122 eta >= getBlockTimestamp().add(delay),
123 "Timelock::queueTransaction: Estimated execution block must satisfy delay."
124 );
125
126 bytes32 txHash = keccak256(
127 abi.encode(target, signature, keccak256(data), eta)
128 );
129 queuedTransactions[txHash] = true;
130
131 emit QueueTransaction(txHash, target, signature, data, eta);
132 return txHash;
133 }
134
135 function cancelTransaction(
136 address target,
137 string memory signature,
138 bytes memory data,
139 uint256 eta
140 ) internal {
141 require(
142 msg.sender == admin,
143 "Timelock::cancelTransaction: Call must come from admin."
144 );
145
146 bytes32 txHash = keccak256(
147 abi.encode(target, signature, keccak256(data), eta)
148 );
149 queuedTransactions[txHash] = false;
150
151 emit CancelTransaction(txHash, target, signature, data, eta);
152 }
153
154 function _getRevertMsg(bytes memory _returnData)
155 internal
156 pure
157 returns (string memory)
158 {
159 // If the _res length is less than 68, then the transaction failed
160 // silently (without a revert message)
161 if (_returnData.length < 68) return "Transaction reverted silently";
162
163 assembly {
164 // Slice the sighash.
165 _returnData := add(_returnData, 0x04)
166 }
167 return abi.decode(_returnData, (string));
168 }
169
170 function executeTransaction(
171 address target,
172 string memory signature,
173 bytes memory data,
174 uint256 eta
175 ) internal returns (bytes memory) {
176 require(
177 msg.sender == admin,
178 "Timelock::executeTransaction: Call must come from admin."
179 );
180
181 bytes32 txHash = keccak256(
182 abi.encode(target, signature, keccak256(data), eta)
183 );
184 require(
185 queuedTransactions[txHash],
186 "Timelock::executeTransaction: Transaction hasn't been queued."
187 );
188 require(
189 getBlockTimestamp() >= eta,
190 "Timelock::executeTransaction: Transaction hasn't surpassed time lock."
191 );
192 require(
193 getBlockTimestamp() <= eta.add(GRACE_PERIOD),
194 "Timelock::executeTransaction: Transaction is stale."
195 );
196
197 queuedTransactions[txHash] = false;
198
199 bytes memory callData;
200
201 if (bytes(signature).length == 0) {
202 callData = data;
203 } else {
204 callData = abi.encodePacked(
205 bytes4(keccak256(bytes(signature))),
206 data
207 );
208 }
209
210 (bool success, bytes memory returnData) = target.call(callData);
211
212 if (!success) {
213 revert(_getRevertMsg(returnData));
214 }
215
216 emit ExecuteTransaction(txHash, target, signature, data, eta);
217
218 return returnData;
219 }
220
221 function getBlockTimestamp() internal view returns (uint256) {
222 // solium-disable-next-line security/no-block-members
223 return block.timestamp;
224 }
225
226 function pauseCapital(address target) external {
227 require(
228 msg.sender == admin,
229 "Timelock::pauseCapital: Call must come from admin."
230 );
231 CapitalPausable(target).pauseCapital();
232 }
233
234 function unpauseCapital(address target) external {
235 require(
236 msg.sender == admin,
237 "Timelock::unpauseCapital: Call must come from admin."
238 );
239 CapitalPausable(tar