One of the largest DEXs in crypto, handling $100 million+ in daily volume and supporting Bitcoin, Ethereum, Cosmoshub, and various UTXO & EVM chains.
Platform: Code4rena
Start Date: 05/06/2024
End Date: 12/06/2024
Period: 7 days
Status: Awarded
Pot Size: $36,500 USDC
Participants: 32
Id: 386
League: ETH
ilchovski | 1/32 | $7,111.05 | 3 | 2 | 0 | 1 | 0 | 0 | 0 | 0 |
samuraii77 | 2/32 | $4,820.15 | 3 | 1 | 0 | 2 | 0 | 0 | 0 | 0 |
rbserver | 3/32 | $3,891.19 | 2 | 1 | 0 | 1 | 0 | 0 | 0 | 0 |
Bauchibred | 4/32 | $3,753.62 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
mt030d | 5/32 | $1,994.24 | 3 | 2 | 0 | 1 | 0 | 0 | 0 | 0 |
cheatc0d3 | 6/32 | $758.41 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
Shaheen | 7/32 | $752.57 | 3 | 1 | 0 | 2 | 0 | 0 | 0 | 0 |
Svetoslavb | 8/32 | $656.27 | 3 | 1 | 0 | 2 | 0 | 0 | 0 | 0 |
Team_RockSolid | 9/32 | $615.00 | 3 | 1 | 0 | 2 | 0 | 0 | 0 | 0 |
Greed | 10/32 | $596.13 | 2 | 1 | 0 | 1 | 0 | 0 | 0 | 0 |
Auditor per page
Note for C4 wardens: Anything included in this Automated Findings / Publicly Known Issues
section is considered a publicly known issue and is ineligible for awards.
If an un-whitelisted token interacts with the Router (for example through the depositWithExpiry function), the tx will effectively be dropped on the floor, as the whitelist is checked in the scp.assetResolver function. The asset resolver + whitelist functionality can be seen here
THORChain is a decentralized, cross-chain liquidity network that replicates the functionality of centralized exchanges on-chain. Its features include native asset swapping, time-weighted average price (TWAP) trades, savings, and lending. The network is maintained by over 100 anonymous and independent validators, each operating a sophisticated stack to secure Layer 1 assets, monitor and sign transactions on external blockchains, and execute business logic on THORChain’s proprietary Cosmos SDK-based blockchain.
THORChain’s Architecture consists of 4 major components. The two components relevant for this contest are the Router Smart Contract and the Bifrost observation & signing interface.
Router Smart Contract (EVM Only) (In scope) https://gitlab.com/thorchain/thornode/-/tree/develop/chain/ethereum
The THORChain router serves as both the entry and exit point for EVM-based gas assets and ERC20 tokens. Users deposit assets using the router's depositWithExpiry function, providing the necessary parameters. THORChain's validators monitor the emitted events from this function to determine the appropriate actions, such as swaps, savings, or loan initiation. For EVM outbound transactions, THORChain’s validators sign and broadcast a transferOut or transferOutAndCall function call on the router. The Router contract holds the network’s ERC20 tokens and manages allowances for each active vault, while gas assets are forwarded to and from the contract and the active vaults. The Router is also used in vault "churn". Retiring vaults will call the Router's transferAllowance function to move ERC20 allowance to newly active vaults.
Bifrost Observation and Signing Interface (Partially in scope) https://gitlab.com/thorchain/thornode/-/tree/develop/bifrost
Bifrost is the observation and signing interface between THORChain and each external blockchain. For each connected blockchain, Bifrost scans each block and monitors for inbound transactions to the network. When a valid inbound transaction is observed, Bifrost posts an observation transaction to THORChain’s Layer 1. Bifrost also handles signing outbound transactions to external blockchains. Once an outbound transaction is assigned to a vault, the Bifrost daemons for each vault invoke THORChain’s TSS library to sign the outbound with its keyshare. After the threshold signature is complete, Bifrost broadcasts the transaction to the external chain.
TSS Library (Not in scope) https://gitlab.com/thorchain/tss/tss-lib https://gitlab.com/thorchain/tss/go-tss
THORChain’s Threshold Signature Scheme (TSS) library is a fork of Binance’s Go-based TSS implementation of the G20 TSS algorithm. The TSS library performs KeyGen and KeySign ceremonies to create, sign outbounds for, and rotate THORChain’s Asgard vaults, which protect the network's external Layer 1 assets.
THORNode - Cosmos SDK Layer 1 (Not in scope)
THORChain’s Layer 1 is a Cosmos chain that executes all business logic for the network, including feature functionality, validator management, vault rotation, rewards distribution, and more.
Note: although all of the Router's functions are public, only depositWithExpiry
is "meant" to be called by external parties. Of course, since the functions are public anyone can call them, but an external party should not be able to impersonate a vault in order to move the network's ERC20s or other assets. This is achieved through the private _vaultAllowance
map, which keeps track of each vault's spendable ERC20s. As users call depositWithExpiry
the target vault's allowance is incremented, and a transferOut
, transferOutAndCall
, or transferAllowance
call will decrement a vault's allowance.
depositWithExpiry - all EVM-based actions on THORChain are initiated through this function. This should increase the target vault's allowance (if an ERC20 is deposited), or increase the vault's ETH balance if ETH is sent in. Params:
Events:
transferOut - intended to only be called by a THORChain vault. transferOut sends gas assets or ERC20s to fulfill an EVM outbound. Params:
Events:
transferOutAndCall - (V4 version) intended to only be called by a THORChain vault. transferOutAndCall calls a whitelisted “aggregator” contract’s swapOut
function that in turn initiates a transaction on a 3rd party protocol. This is used to daisy chain swaps with external liquidity, enabling swaps such as $DOGE -> $SHIB (DOGE → ETH on THORChain, and ETH → SHIB on Uniswap).
Params:
transferOutAndCallV5 - intended to only be called by a THORChain vault. transferOutAndCall calls a whitelisted “aggregator” contract’s swapOut
function that in turn initiates a transaction on a 3rd party protocol. This is used to daisy chain swaps with external liquidity, enabling swaps such as $DOGE -> $SHIB (DOGE → ETH on THORChain, and ETH → SHIB on Uniswap).
Params:
Events:
transferAllowance - intended to only be called by a THORChain vault. transferAllowance is used during “churns” (i.e. vault rotation). Retiring vaults transfer their allowance to spend ERC20 tokens on the router to the new vaults. Params:
_transferOutV5 - same functionality as transferOut, but without reentrancy protection so it can be used in the batchTransferOut function
transferOutV5 - non-reentrant wrapper around _transferOutV5
batchTransferOutV5 - intended to only be called by a THORChain vault. Batch an array of transferOutV5 calls.
The most important part of Bifrost for this audit contest is the smartcontract_log_parser, and specifically the GetTxInItem function. The GetTxInItem is run for each obvserve transaction on EVM chains. The function iterates through each log emitted by the transaction, and determines if any valid logs were emitted by the THORChain router. If it determines that a log was emitted by the THORChain router, it parses that log and forwards the appropriate details to the THORChain Layer 1 for processing. This is an incredibly sensitive and crucial piece of the codebase, as if it can be tricked, this means malicious contracts can trick Bifrost into informing THORChain of something that didn’t actually happen, leading to loss of funds. In fact, in July of 2021, THORChain’s old router + Bifrost were hacked in this exact way. Details of those hacks:
https://rekt.news/thorchain-rekt/ https://rekt.news/thorchain-rekt2/
After the July 2021 hacks, THORChain implemented a whitelist for smart contracts that are able to interact with the Router - this was implemented in the Bifrost layer (txs to contracts not whitelisted would be ignored). THORChain is now removing this whitelist, so an important focus of this audit contest is if removing the whitelist will open any vulnerabilities. Wardens will need to understand both the Router functionality and the Bifrost transaction parsing to properly delve into this problem space.
This contest is focused on THORChain Removal of Whitelisting on Router and Router V5
Contract | SLOC | Purpose | Libraries used |
---|---|---|---|
chain/ethereum/contracts/THORChain_Router.sol | 378 | ||
bifrost/pkg/chainclients/shared/evm/smartcontract_log_parser.go | 315 | ||
bifrost/pkg/chainclients/ethereum/ethereum_block_scanner.go | 824 | ||
TOTAL | 1517 |
All files not listed above are Out Of Scope.
This function of Router V5 is out of scope: returnVaultAssets
Question | Answer |
---|---|
ERC20 used by the protocol | Any (all possible ERC20s) |
Test coverage | Ethereum: Functions - 46.91% , Lines - 49.33% , Avalanche: Functions - 100%, Lines - 97.44% |
ERC721 used by the protocol | None |
ERC777 used by the protocol | None |
ERC1155 used by the protocol | None |
Chains the protocol will be deployed on | Ethereum, Avax, BSC |
Question | Answer |
---|---|
Enabling/disabling fees (e.g. Blur disables/enables fees) | No |
Pausability (e.g. Uniswap pool gets paused) | No |
Upgradeability (e.g. Uniswap gets upgraded) | No |
None
depositWithExpiry
should be rejected if it is confirmed after the expiration parameter.transferOut
should only update the allowance mapping if the ERC20 transfer was successful.transferOut
should only allow ERC20s to be transferred from the Router if msg.sender has the appropriate allowance for the asset stored in the _vaultAllowances
map.transferAllowance
should only update the _vaultAllowances
map if msg.sender
already has the appropriate allowance for the asset.deposit
should forward ETH directly to the provided vault address.deposit
should keep ERC20s on the router contract and update the vault allowance.GetTxInItem
function of the smartcontract_log_parsermax_contract_tx_logs
should be ignored by the GetTxInItem
function of the smartcontract_log_parser
smartcontract_log_parser
, and therefore the network, into thinking a DepositEvent has been emitted by the THORChain router when in fact it was emitted by a different contract. If this is possible, then an attacker could send in a fake swap or other transaction and extract value from THORChain's liquidity pools.smartcontract_log_parser
that the DepositEvent has a different amount of ETH or ERC20s that were actually sent in by the transaction._vaultAllowance
) to transfer out ERC20 tokens from the Router using transferOut
, transferOutAndCall
, transferOutV5
, transferOutAndCallV5
, batchTransferOut
, or batchTransferOutAndCallV5
transferAllowance
function or otherwiseNone
None
[!NOTE] More detailed build, compile, and test instructions found in contract repo README: https://gitlab.com/thorchain/thornode/-/tree/develop/chain/ethereum
git clone https://github.com/code-423n4/2024-06-thorchain.git git submodule update --init --recursive cd ethereum npx hardhat clean npx hardhat compile npx hardhat test cd avalanche npx hardhat clean npx hardhat compile npx hardhat test
To run code coverage
npx hardhat coverage
Employees of Thorchain and employees' family members are ineligible to participate in this audit.