If you notice some outdated information please let us know!
FAIL
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://stargateprotocol.gitbook.io/stargate/developers/contract-addresses/mainnet, as indicated in the Appendix.
2. How active is the primary contract? (%)
Contract Router.sol is used 200+ times a day, as indicated in the Appendix.
3. Does the protocol have a public software repository? (Y/N)
Location: https://github.com/stargate-protocol
4. Is there a development history visible? (%)
At just 4 commits, this protocol does not have a good development history visible.
5. Is the team public (not anonymous)?
Stargate is strapiuced by LayerZero Labs. The employees of this company are listed on LinkedIn.
This section looks at the software documentation. The document explaining these questions is here.
6. Is there a whitepaper? (Y/N)
Location: https://stargateprotocol.gitbook.io/stargate/
7. Is the protocol's software architecture documented? (Y/N)
This protocol's software architecture is not documented in their documentation. No diagrams / explanations as to how the contracts relate to each other were detailed. Nevertheless, nonspecific mentions of how contracts interrelate to one another are detailed in the whitepaper.
8. Does the software documentation fully cover the deployed contracts' source code? (%)
There is some coverage of deployed contracts by software function documentation. Nevertheless, main contracts like Router.sol / Factory.sol are not covered.
9. Is it possible to trace the documented software to its implementation in the protocol's source code? (%)
There is good (but not explicit) traceability between software documentation and implemented code.
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 181% 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? (%)
This protocol documents no tests for code coverage. Nevertheless, with 181% TtC we can assume there is good testing on Stargate.
12. Does the protocol provide scripts and instructions to run their tests? (Y/N)
Scripts/Instructions location: https://github.com/stargate-protocol/stargate#testing
13. Is there a detailed report of the protocol's test results?(%)
There is no test report documented by Stargate.
14. Has the protocol undergone Formal Verification? (Y/N)
Stargate has not undergone formal verification.
15. Were the smart contracts deployed to a testnet? (Y/N)
This protocol has been deployed to a testnet. In providing this, Stargate enables users to independently verify these using a block explorer.
This section looks at the 3rd party software audits done. It is explained in this document.
16. Is the protocol sufficiently audited? (%)
Stargate was audited twice before launch and once after.
17. Is the bounty value acceptably high (%)
Stargate does not offer a bug bounty at time of writing.
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 documented by Stargate. It is labelled under their governance section.
19. Are relevant contracts clearly labelled as upgradeable or immutable? (%)
Stargate's relevant contracts are not identified as immutable / upgradeable.
20. Is the type of smart contract ownership clearly indicated? (%)
Ownership is clearly indicated as being in the hands of a multisig. This may change as the governance processes develop.
21. Are the protocol's smart contract change capabilities described? (%)
Stargate's smart contract change capabilities are identified in non-specific contracts.
22. Is the protocol's admin control information easy to understand? (%)
Stargate's admin control information is in software specific language, and does not relate to the safety of user investments.
23. Is there sufficient Pause Control documentation? (%)
Stargate's pause control is not documented.
24. Is there sufficient Timelock documentation? (%)
Stargate has no timelock documentation.
25. Is the Timelock of an adequate length? (Y/N)
Stargate has no timelock documentation, and we therefore cannot evaluate its lenght.
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. These questions are explained in this document.
26. Is the protocol's Oracle sufficiently documented? (%)
Stargate's data source is not documented. The contracts dependent are not identified. There is no relevant software function documentation.
27. Is front running mitigated by this protocol? (Y/N)
Stargate is a bridge, and is therefore is not susceptible to front-running. Stargate provides guaranteed instant finality, meaning that whatever amount of funds you bridge will be equivalently minted on the other side.
28. Can flashloan attacks be applied to the protocol, and if so, are those flashloan attack risks mitigated? (Y/N)
Stargate documents no flash loan exploit countermeasures.
1// SPDX-License-Identifier: BUSL-1.1
2
3pragma solidity 0.7.6;
4pragma abicoder v2;
5
6// imports
7import "@openzeppelin/contracts/access/Ownable.sol";
8import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
9import "./LPTokenERC20.sol";
10import "./interfaces/IStargateFeeLibrary.sol";
11
12// libraries
13import "@openzeppelin/contracts/math/SafeMath.sol";
14
15/// Pool contracts on other chains and managed by the Stargate protocol.
16contract Pool is LPTokenERC20, ReentrancyGuard {
17 using SafeMath for uint256;
18
19 //---------------------------------------------------------------------------
20 // CONSTANTS
21 bytes4 private constant SELECTOR = bytes4(keccak256(bytes("transfer(address,uint256)")));
22 uint256 public constant BP_DENOMINATOR = 10000;
23
24 //---------------------------------------------------------------------------
25 // STRUCTS
26 struct ChainPath {
27 bool ready; // indicate if the counter chainPath has been created.
28 uint16 dstChainId;
29 uint256 dstPoolId;
30 uint256 weight;
31 uint256 balance;
32 uint256 lkb;
33 uint256 credits;
34 uint256 idealBalance;
35 }
36
37 struct SwapObj {
38 uint256 amount;
39 uint256 eqFee;
40 uint256 eqReward;
41 uint256 lpFee;
42 uint256 protocolFee;
43 uint256 lkbRemove;
44 }
45
46 struct CreditObj {
47 uint256 credits;
48 uint256 idealBalance;
49 }
50
51 //---------------------------------------------------------------------------
52 // VARIABLES
53
54 // chainPath
55 ChainPath[] public chainPaths; // list of connected chains with shared pools
56 mapping(uint16 => mapping(uint256 => uint256)) public chainPathIndexLookup; // lookup for chainPath by chainId => poolId =>index
57
58 // metadata
59 uint256 public immutable poolId; // shared id between chains to represent same pool
60 uint256 public sharedDecimals; // the shared decimals (lowest common decimals between chains)
61 uint256 public localDecimals; // the decimals for the token
62 uint256 public immutable convertRate; // the decimals for the token
63 address public immutable token; // the token for the pool
64 address public immutable router; // the token for the pool
65
66 bool public stopSwap; // flag to stop swapping in extreme cases
67
68 // Fee and Liquidity
69 uint256 public totalLiquidity; // the total amount of tokens added on this side of the chain (fees + deposits - withdrawals)
70 uint256 public totalWeight; // total weight for pool percentages
71 uint256 public mintFeeBP; // fee basis points for the mint/deposit
72 uint256 public protocolFeeBalance; // fee balance created from dao fee
73 uint256 public mintFeeBalance; // fee balance created from mint fee
74 uint256 public eqFeePool; // pool rewards in Shared Decimal format. indicate the total budget for reverse swap incentive
75 address public feeLibrary; // address for retrieving fee params for swaps
76
77 // Delta related
78 uint256 public deltaCredit; // credits accumulated from txn
79 bool public batched; // flag to indicate if we want batch processing.
80 bool public defaultSwapMode; // flag for the default mode for swap
81 bool public defaultLPMode; // flag for the default mode for lp
82 uint256 public swapDeltaBP; // basis points of poolCredits to activate Delta in swap
83 uint256 public lpDeltaBP; // basis points of poolCredits to activate Delta in liquidity events
84
85 //---------------------------------------------------------------------------
86 // EVENTS
87 event Mint(address to, uint256 amountLP, uint256 amountSD, uint256 mintFeeAmountSD);
88 event Burn(address from, uint256 amountLP, uint256 amountSD);
89 event RedeemLocalCallback(address _to, uint256 _amountSD, uint256 _amountToMintSD);
90 event Swap(
91 uint16 chainId,
92 uint256 dstPoolId,
93 address from,
94 uint256 amountSD,
95 uint256 eqReward,
96 uint256 eqFee,
97 uint256 protocolFee,
98 uint256 lpFee
99 );
100 event SendCredits(uint16 dstChainId, uint256 dstPoolId, uint256 credits, uint256 idealBalance);
101 event RedeemRemote(uint16 chainId, uint256 dstPoolId, address from, uint256 amountLP, uint256 amountSD);
102 event RedeemLocal(address from, uint256 amountLP, uint256 amountSD, uint16 chainId, uint256 dstPoolId, bytes to);
103 event InstantRedeemLocal(address from, uint256 amountLP, uint256 amountSD, address to);
104 event CreditChainPath(uint16 chainId, uint256 srcPoolId, uint256 amountSD, uint256 idealBalance);
105 event SwapRemote(address to, uint256 amountSD, uint256 protocolFee, uint256 dstFee);
106 event WithdrawRemote(uint16 srcChainId, uint256 srcPoolId, uint256 swapAmount, uint256 mintAmount);
107 event ChainPathUpdate(uint16 dstChainId, uint256 dstPoolId, uint256 weight);
108 event FeesUpdated(uint256 mintFeeBP);
109 event FeeLibraryUpdated(address feeLibraryAddr);
110 event StopSwapUpdated(bool swapStop);
111 event WithdrawProtocolFeeBalance(address to, uint256 amountSD);
112 event WithdrawMintFeeBalance(address to, uint256 amountSD);
113 event DeltaParamUpdated(bool batched, uint256 swapDeltaBP, uint256 lpDeltaBP, bool defaultSwapMode, bool defaultLPMode);
114
115 //---------------------------------------------------------------------------
116 // MODIFIERS
117 modifier onlyRouter() {
118 require(msg.sender == router, "Stargate: only the router can call this method");
119 _;
120 }
121
122 constructor(
123 uint256 _poolId,
124 address _router,
125 address _token,
126 uint256 _sharedDecimals,
127 uint256 _localDecimals,
128 address _feeLibrary,
129 string memory _name,
130 string memory _symbol
131 ) LPTokenERC20(_name, _symbol) {
132 require(_token != address(0x0), "Stargate: _token cannot be 0x0");
133 require(_router != address(0x0), "Stargate: _router cannot be 0x0");
134 poolId = _poolId;
135 router = _router;
136 token = _token;
137 sharedDecimals = _sharedDecimals;
138 decimals = uint8(_sharedDecimals);
139 localDecimals = _localDecimals;
140 convertRate = 10**(uint256(localDecimals).sub(sharedDecimals));
141 totalWeight = 0;
142 feeLibrary = _feeLibrary;
143
144 //delta algo related
145 batched = false;
146 defaultSwapMode = true;
147 defaultLPMode = true;
148 }
149
150 function getChainPathsLength() public view returns (uint256) {
151 return chainPaths.length;
152 }
153
154 //---------------------------------------------------------------------------
155 // LOCAL CHAIN FUNCTIONS
156
157 function mint(address _to, uint256 _amountLD) external nonReentrant onlyRouter returns (uint256) {
158 return _mintLocal(_to, _amountLD, true, true);
159 }
160
161 // Local Remote
162 // ------- ---------
163 // swap -> swapRemote
164 function swap(
165 uint16 _dstChainId,
166 uint256 _dstPoolId,
167 address _from,
168 uint256 _amountLD,
169 uint256 _minAmountLD,
170 bool newLiquidity
171 ) external nonReentrant onlyRouter returns (SwapObj memory) {
172 require(!stopSwap, "Stargate: swap func stopped");
173 ChainPath storage cp = getAndCheckCP(_dstChainId, _dstPoolId);
174 require(cp.ready == true, "Stargate: counter chainPath is not ready");
175
176 uint256 amountSD = amountLDtoSD(_amountLD);
177 uint256 minAmountSD = amountLDtoSD(_minAmountLD);
178
179 // request fee params from library
180 SwapObj memory s = IStargateFeeLibrary(feeLibrary).getFees(poolId, _dstPoolId, _dstChainId, _from, amountSD);
181
182 // equilibrium fee and reward. note eqFee/eqReward are separated from swap liquidity
183 eqFeePool = eqFeePool.sub(s.eqReward);
184 // update the new amount the user gets minus the fees
185 s.amount = amountSD.sub(s.eqFee).sub(s.protocolFee).sub(s.lpFee);
186 // users will also get the eqReward
187 require(s.amount.add(s.eqReward) >= minAmountSD, "Stargate: slippage too high");
188
189 // behaviours
190 // - protocolFee: booked, stayed and withdrawn at remote.
191 // - eqFee: booked, stayed and withdrawn at remote.
192 // - lpFee: booked and stayed at remote, can be withdrawn anywhere
193
194 s.lkbRemove = amountSD.sub(s.lpFee).add(s.eqReward);
195 // check for transfer solvency.
196 require(cp.balance >= s.lkbRemove, "Stargate: dst balance too low");
197 cp.balance = cp.balance.sub(s.lkbRemove);
198
199 if (newLiquidity) {
200 deltaCredit = deltaCredit.add(amountSD).add(s.eqReward);
201 } else if (s.eqReward > 0) {
202 deltaCredit = deltaCredit.add(s.eqReward);
203 }
204
205 // distribute credits on condition.
206 if (!batched || deltaCredit >= totalLiquidity.mul(swapDeltaBP).div(BP_DENOMINATOR)) {
207 _delta(defaultSwapMode);
208 }
209
210 emit Swap(_dstChainId, _dstPoolId, _from, s.amount, s.eqReward, s.eqFee, s.protocolFee, s.lpFee);
211 return s;
212 }
Tests to Code: 2667 / 1470 = 181 %