Skip to content

Commit

Permalink
yongskiws data for issue #895
Browse files Browse the repository at this point in the history
  • Loading branch information
c4-submissions committed Oct 6, 2023
1 parent ee91d87 commit 9b9d35c
Showing 1 changed file with 286 additions and 0 deletions.
286 changes: 286 additions & 0 deletions data/yongskiws-Analysis.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,286 @@
### Architecture Description and Diagram

`ArbitrumBranchBridgeAgent`

ArbitrumBranchBridgeAgent is a derivative of the BranchBridgeAgent contract and is used as an intermediary agent to access LayerZero cross-chain communications and Port communications.

ArbitrumBranchBridgeAgent contract also has several important external functions, including depositToPort and withdrawFromPort, which are used to deposit and withdraw assets to/from the local Port.

`ArbitrumBranchPort`

ArbitrumBranchPort contract has two important external functions, namely depositToPort and withdrawFromPort, which are used to deposit and withdraw assets to/from the local Port. This second function has a modification lock that ensures that only one transaction can be executed at a time.

`ArbitrumCoreBranchRouter`

executeNoSettlement to execute various system functions. It can process several types of operations such as adding a Bridge Agent, replacing a Factory Bridge Agent, removing a Bridge Agent, managing strategy tokens, and more. This function receives data containing system function calls via cross-chain messaging.

`BranchBridgeAgent`

Main Functions: has various main functions, such as deposit creation, signed cross-chain invocation, invocation with fallback handling, and so on. These functions allow users to initiate and manage transfers between chains.

Error Handling: BranchBridgeAgent also comes with an error handling mechanism. If there is an error in cross-chain transaction execution, such as a failed execution, has the ability to return the deposit to the sender or activate a fallback to reprocess.

Inter-Chain Communication: uses LayerZero, which is a cross-chain messaging layer, to communicate with other chains in the network. This enables secure and efficient transfers between chains.

Modifiers and Verification: uses modifiers to ensure that only authorized parties can access certain functions. It is designed to increase security and prevent protection.

Documentation: also includes documentation in the form of comments, which explains the logic and use of the functions.

`BaseBranchRouter`

BaseBranchRouter stores several important addresses used in the ecosystem, including local bridge agent addresses and bridge agent executing addresses. This data is used to direct communications and asset transfers. also regulates the approval required for the use of these assets in cross-chain transactions.

`BranchPort`

1.Port Strategy decisions to manage tokens and port management strategies.
2.Triggers the user to recharge reserve tokens.
3.Users longing to transfer tokens cross-chain.
4.Asks the owner to update the ecosystem by adding new Bridge Agents, Factories and Port Strategies.

Risk Security:
includes multiple layers of security, including sender message verification, daily settings for Port Strategy, and token reserve replenishment. This helps ensure that users and port management strategies can operate securely.


### My Thoughts

Ulysses Protocol is a decentralized Omnichain Liquidity Protocol aimed at optimizing liquidity management in DeFi. It allows Liquidity Providers to deploy assets across multiple chains, earn revenue from various chains, and reduce operational costs for DeFi protocols. The protocol has two key components: Virtualized and Unified Liquidity Management. It uses Arbitrum's Balancer's Composable Stable Pools and enables a single token representing stable LP from different chains for full composability. Understanding Ulysses Ports and Virtualized Liquidity is crucial, and cross-chain messaging is facilitated through Layer0. Explore Ulysses Unified Tokens for insights into stable pools and liquidity architecture.

### Systemic Risks

Block Timestamp Settings: Different chains may have varying requirements for block timestamp settings. This could lead to discrepancies or challenges in managing timestamps across chains.

Gas Refunds: When using a Virtual Account as a refundee for cross-chain messages, excess gas refunds on branch chains may become inaccessible. This is because the refundee is not an Externally Owned Account (EOA) capable of claiming funds on branch chains.

Pragma Version: The code will be deployed with pragma version 0.8.19, which may have implications for compatibility and functionality with different Solidity versions.

Ownership Renouncement: Some contracts allow for the renouncement of ownership without overriding the renounceOwnership function from the Solady library. This could potentially lead to unexpected consequences.

Permissionless Factories: The protocol includes permissionless factories, where anyone can create contracts. This opens the possibility for the creation of malicious contracts or the deposit of potentially harmful tokens in ports. While contracts generated by these actions are not in the protocol's scope, they may impact other contracts or balances.

Admin Functions: Most admin functions can only be called by other contracts in the system or by Hermes Protocol's Governance. However, RootBridgeAgent Managers are open to whoever creates them. Misuse of these functions by Hermes Governance is out of scope, except when it affects other contracts or balances. If a Manager of RootBridgeAgent misuses these functions and it has an impact on other contracts or balances, it is considered a valid concern.


### Centralization Risks

Control by a Single Party: This risk occurs when one entity or a small group has significant control over assets or critical functions within the protocol. This can lead to manipulation or unfair decision-making.

Key Contractors: If there are key contractors or third parties with a pivotal role in the development, maintenance, or operation of the protocol, centralization risk can arise if there is excessive dependence on that entity.

Centralized Governance Power: This risk is related to strong control by a single entity or group in the decision-making process and rule-setting within the protocol. It can undermine the desired decentralization aspects of DeFi.

Use of Power Tokens: If tokens that grant voting rights or control in the protocol are owned by a small number of individuals or entities, centralization risk can emerge due to the significant control held by these parties.

Single-Asset Risk: Centralization can also occur if the protocol is heavily reliant on a single asset or a specific blockchain chain. This dependency can lead to vulnerabilities if the asset or chain experiences issues.

### Architecture Recommendations

Emergency Monitoring and Response: Have a robust monitoring system and emergency response plan to quickly address operational issues.

Security Planning: recommends robust security planning to deal with emergency situations and effective vulnerability reporting.

Comprehensive Testing: Perform comprehensive unit testing and integration testing to verify proper functioning of the protocol.

Smart Contract Upgrades: Consider secure smart capability upgrade mechanisms so that the protocol can evolve over time without risk of vulnerabilities.

Strong Documentation: Provides strong documentation for the source code so that developers, users, and third parties can easily understand how the protocol works.

Solidity Best Practices: follow Solidity best practices in writing code, such as avoiding using constructs that are vulnerable to attack and avoiding using functions that require excessive gas.

Modularity: Building protocols with a modular approach that allows components to interact separately. This makes maintenance and future development easier.

### TREE CODE

```
src\ArbitrumBranchBridgeAgent.sol ^0.8.0
├── src\interfaces\IArbitrumBranchPort.sol ^0.8.0
│ └── src\interfaces\IBranchPort.sol ^0.8.0
├── src\interfaces\IRootBridgeAgent.sol ^0.8.0
│ ├── src\interfaces\ILayerZeroReceiver.sol >=0.5.0
│ └── src\interfaces\BridgeAgentStructs.sol ^0.8.0
├── src\interfaces\IBranchBridgeAgent.sol ^0.8.0
│ ├── src\interfaces\ILayerZeroReceiver.sol >=0.5.0
│ └── src\interfaces\BridgeAgentStructs.sol ^0.8.0
└── src\BranchBridgeAgent.sol ^0.8.0
├── lib/ExcessivelySafeCall.sol >=0.7.6
├── src\interfaces\IBranchPort.sol ^0.8.0
├── src\interfaces\BridgeAgentConstants.sol ^0.8.0
├── src\interfaces\IBranchBridgeAgent.sol ^0.8.0 (*)
├── src\interfaces\ILayerZeroEndpoint.sol >=0.5.0
│ └── src\interfaces\ILayerZeroUserApplicationConfig.sol >=0.5.0
└── src\BranchBridgeAgentExecutor.sol ^0.8.0
├── lib/solady/src/auth/Ownable.sol ^0.8.4
├── lib/solady/src/utils/SafeTransferLib.sol ^0.8.4
├── src\interfaces\IBranchRouter.sol ^0.8.0
│ └── src\interfaces\IBranchBridgeAgent.sol ^0.8.0 (*)
├── src\BranchBridgeAgent.sol ^0.8.0 (*)
├── src\interfaces\BridgeAgentConstants.sol ^0.8.0
└── src\interfaces\IBranchBridgeAgent.sol ^0.8.0 (*)
src\ArbitrumBranchPort.sol ^0.8.0
├── lib/solady/src/utils/SafeTransferLib.sol ^0.8.4
├── src\interfaces\IArbitrumBranchPort.sol ^0.8.0 (*)
├── src\interfaces\IRootPort.sol ^0.8.0
│ ├── src\interfaces\IRootBridgeAgent.sol ^0.8.0 (*)
│ └── src\VirtualAccount.sol ^0.8.0
│ ├── lib/solady/src/utils/SafeTransferLib.sol ^0.8.4
│ ├── lib/solmate/src/tokens/ERC721.sol >=0.8.0
│ ├── lib/openzeppelin-contracts/contracts/token/ERC1155/utils/ERC1155Receiver.sol ^0.8.0
│ │ ├── lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol ^0.8.0
│ │ │ └── lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol ^0.8.0
│ │ └── lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol ^0.8.0
│ │ └── lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol ^0.8.0
│ ├── lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol ^0.8.0 (*)
│ ├── lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol ^0.8.0
│ ├── src\interfaces\IVirtualAccount.sol ^0.8.0
│ │ └── lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol ^0.8.0
│ └── src\interfaces\IRootPort.sol ^0.8.0 (*)
└── src\BranchPort.sol ^0.8.0
├── lib/solady/src/auth/Ownable.sol ^0.8.4
├── lib/solady/src/utils/SafeTransferLib.sol ^0.8.4
├── lib/solmate/src/tokens/ERC20.sol >=0.8.0
├── src\interfaces\IPortStrategy.sol ^0.8.0
├── src\interfaces\IBranchPort.sol ^0.8.0
└── src\token\ERC20hTokenBranch.sol ^0.8.0
├── lib/solady/src/auth/Ownable.sol ^0.8.4
├── lib/solmate/src/tokens/ERC20.sol >=0.8.0
└── src\interfaces\IERC20hTokenBranch.sol ^0.8.0
src\ArbitrumCoreBranchRouter.sol ^0.8.0
├── lib/solmate/src/tokens/ERC20.sol >=0.8.0
├── src\interfaces\IBranchBridgeAgent.sol ^0.8.0 (*)
├── src\interfaces\IBranchBridgeAgentFactory.sol ^0.8.0
├── src\interfaces\IArbitrumBranchPort.sol ^0.8.0 (*)
└── src\CoreBranchRouter.sol ^0.8.0
├── lib/solmate/src/tokens/ERC20.sol >=0.8.0
├── src\interfaces\IBranchPort.sol ^0.8.0
├── src\interfaces\IBranchBridgeAgent.sol ^0.8.0 (*)
├── src\interfaces\IBranchBridgeAgentFactory.sol ^0.8.0
├── src\interfaces\IBranchRouter.sol ^0.8.0 (*)
├── src\interfaces\ICoreBranchRouter.sol ^0.8.0
│ └── src\interfaces\IBranchBridgeAgent.sol ^0.8.0 (*)
├── src\interfaces\IERC20hTokenBranchFactory.sol ^0.8.0
│ └── src\token\ERC20hTokenBranch.sol ^0.8.0 (*)
├── src\BaseBranchRouter.sol ^0.8.0
│ ├── lib/solady/src/auth/Ownable.sol ^0.8.4
│ ├── lib/solady/src/utils/SafeTransferLib.sol ^0.8.4
│ ├── lib/solmate/src/tokens/ERC20.sol >=0.8.0
│ ├── src\interfaces\IBranchRouter.sol ^0.8.0 (*)
│ └── src\interfaces\IBranchBridgeAgent.sol ^0.8.0 (*)
└── src\token\ERC20hTokenBranch.sol ^0.8.0 (*)
src\BaseBranchRouter.sol ^0.8.0 (*)
src\BranchBridgeAgent.sol ^0.8.0 (*)
src\BranchBridgeAgentExecutor.sol ^0.8.0 (*)
src\BranchPort.sol ^0.8.0 (*)
src\CoreBranchRouter.sol ^0.8.0 (*)
src\CoreRootRouter.sol ^0.8.0
├── lib/solady/src/auth/Ownable.sol ^0.8.4
├── lib/solmate/src/tokens/ERC20.sol >=0.8.0
├── src\interfaces\IERC20hTokenRootFactory.sol ^0.8.0
│ └── src\token\ERC20hTokenRoot.sol ^0.8.0
│ ├── lib/solady/src/auth/Ownable.sol ^0.8.4
│ ├── lib/solmate/src/tokens/ERC20.sol >=0.8.0
│ └── src\interfaces\IERC20hTokenRoot.sol ^0.8.0
├── src\interfaces\IRootRouter.sol ^0.8.0
│ └── src\interfaces\IRootBridgeAgent.sol ^0.8.0 (*)
├── src\interfaces\IRootBridgeAgent.sol ^0.8.0 (*)
└── src\interfaces\IRootPort.sol ^0.8.0 (*)
src\MulticallRootRouter.sol ^0.8.0
├── lib/solady/src/auth/Ownable.sol ^0.8.4
├── lib/solady/src/utils/SafeTransferLib.sol ^0.8.4
├── src\interfaces\IMulticall2.sol ^0.8.0
├── src\interfaces\IRootBridgeAgent.sol ^0.8.0 (*)
├── src\interfaces\IRootRouter.sol ^0.8.0 (*)
└── src\interfaces\IVirtualAccount.sol ^0.8.0 (*)
src\MulticallRootRouterLibZip.sol ^0.8.0
├── lib/solady/src/utils/LibZip.sol ^0.8.4
└── src\MulticallRootRouter.sol ^0.8.0 (*)
src\RootBridgeAgent.sol ^0.8.0
├── lib/solady/src/utils/SafeTransferLib.sol ^0.8.4
├── lib/ExcessivelySafeCall.sol >=0.7.6
├── src\interfaces\ILayerZeroEndpoint.sol >=0.5.0 (*)
├── src\interfaces\IBranchBridgeAgent.sol ^0.8.0 (*)
├── src\interfaces\IERC20hTokenRoot.sol ^0.8.0
├── src\interfaces\BridgeAgentConstants.sol ^0.8.0
├── src\interfaces\IRootBridgeAgent.sol ^0.8.0 (*)
├── src\interfaces\IRootPort.sol ^0.8.0 (*)
├── src\VirtualAccount.sol ^0.8.0 (*)
└── src\RootBridgeAgentExecutor.sol ^0.8.0
├── lib/solady/src/auth/Ownable.sol ^0.8.4
├── src\interfaces\IRootRouter.sol ^0.8.0 (*)
├── src\interfaces\IRootBridgeAgent.sol ^0.8.0 (*)
├── src\interfaces\BridgeAgentConstants.sol ^0.8.0
└── src\RootBridgeAgent.sol ^0.8.0 (*)
src\RootBridgeAgentExecutor.sol ^0.8.0 (*)
src\RootPort.sol ^0.8.0
├── lib/solady/src/auth/Ownable.sol ^0.8.4
├── lib/solady/src/utils/SafeTransferLib.sol ^0.8.4
├── src\interfaces\IERC20hTokenRootFactory.sol ^0.8.0 (*)
├── src\interfaces\IRootBridgeAgent.sol ^0.8.0 (*)
├── src\interfaces\IRootPort.sol ^0.8.0 (*)
└── src\token\ERC20hTokenRoot.sol ^0.8.0 (*)
src\VirtualAccount.sol ^0.8.0 (*)
src\factories\ArbitrumBranchBridgeAgentFactory.sol ^0.8.0
├── src\interfaces\IArbitrumBranchPort.sol ^0.8.0 (*)
├── src\ArbitrumBranchBridgeAgent.sol ^0.8.0 (*)
└── src\factories\BranchBridgeAgentFactory.sol ^0.8.0
├── lib/solady/src/auth/Ownable.sol ^0.8.4
├── src\BranchBridgeAgent.sol ^0.8.0 (*)
├── src\interfaces\IBranchPort.sol ^0.8.0
└── src\interfaces\IBranchBridgeAgentFactory.sol ^0.8.0
src\factories\BranchBridgeAgentFactory.sol ^0.8.0 (*)
src\factories\ERC20hTokenBranchFactory.sol ^0.8.0
├── lib/solady/src/auth/Ownable.sol ^0.8.4
├── src\token\ERC20hTokenBranch.sol ^0.8.0 (*)
└── src\interfaces\IERC20hTokenBranchFactory.sol ^0.8.0 (*)
src\factories\ERC20hTokenRootFactory.sol ^0.8.0
├── lib/solady/src/auth/Ownable.sol ^0.8.4
├── lib/solmate/src/tokens/ERC20.sol >=0.8.0
└── src\interfaces\IERC20hTokenRootFactory.sol ^0.8.0 (*)
src\factories\RootBridgeAgentFactory.sol ^0.8.0
├── src\interfaces\IRootBridgeAgentFactory.sol ^0.8.0
├── src\interfaces\IRootPort.sol ^0.8.0 (*)
└── src\RootBridgeAgent.sol ^0.8.0 (*)
```

### Gas Optimizations

Lock modifiers are used in some contract functions to prevent reentrance. This is a good approach to avoid reentrance attacks, but keep in mind that this modifier will consume additional gas on each function call that uses this modifier. Therefore, it is necessary to ensure that the use of the lock modifier is justified and necessary in each case.

Some arithmetic operations, such as subtraction and multiplication, can require significant gas depending on the number of binary digits. It is worth checking whether these operations can be optimized or replaced with more efficient approaches.

Function calls from other or external contracts usually require more gas than internal function calls. Make sure external function calls are only used when absolutely necessary and consider more gas-efficient alternatives whenever possible.

Looping can waste significant gas if not managed properly. Ensure that iterations in contract functions do not exceed the maximum gas limit allowed in an Ethereum block.

Mapping can consume gas if used in complex operations. Ensure the use of efficient mappings and consider whether some mappings can be replaced with other, more gas-efficient data structures.

External calls with gas stipends can be used to avoid "out of gas" errors, but they can also lead to potential reentrance attacks. Make sure that resuming external calls are used carefully and only when necessary.

The unchecked keyword is used in some parts of the code to avoid throwing under certain conditions. This can speed up execution, but also increases the risk of errors. Ensure safe and appropriate use of unchecked.

Please note that the total block size of Ethereum transactions has limits. If contract functions produce very large outputs, this may result in transactions being too large to be included in the block.

It is important to understand that there is a maximum gas limit that can be assigned to an Relaying Messages to the Layer Zero Endpoint transaction. If a function requires more gas than the maximum limit, the transaction will fail. Therefore, it is necessary to ensure that each function operates within reasonable gas limits.

When compiling contracts using Solidity, the optimizer configuration can impact gas usage. The use of optimizers such as --optimize and --runs needs to be considered to achieve more efficient results.

Using token.balanceOf(address(this)) Branch Port every time can potentially reduce the contract's performance. Frequent external calls to other contracts, such as reading the balance of the token contract, can be expensive in terms of gas costs and execution time. This can lead to higher transaction costs and slower contract execution

Explicitly initializing default values for variables consumes additional gas during contract deployment. If you rely on the EVM's automatic default initialization, you can save gas costs associated with these unnecessary operations

Minimize the number of state variable reads and writes. Use local variables when possible to avoid additional storage operations

Limit the number of iterations in loops to prevent excessive gas consumption. Consider using other patterns like mapping, where possible, to reduce the need for loops

Whenever applicable, consider batching multiple operations together to save on gas costs. For example, you can combine multiple token transfers into a single function call

Remove any unused or commented-out code to save space and simplify contract logic

Check if modifiers can be combined or reused across multiple functions to reduce the number of modifier calls. This can save gas by avoiding redundant checks.

Consider batching the make emit events in every function or using other gas-saving techniques to reduce transaction costs

Reuse variables instead of creating new ones when possible. This can reduce memory usage and, in turn, save gas



### Time spent:
15 hours

0 comments on commit 9b9d35c

Please sign in to comment.