Axelar Network v2 contest - Respx's results

Decentralized interoperability network.

General Information

Platform: Code4rena

Start Date: 29/07/2022

Pot Size: $50,000 USDC

Total HM: 6

Participants: 75

Period: 5 days

Judge: GalloDaSballo

Total Solo HM: 3

Id: 149

League: ETH

Axelar Network

Findings Distribution

Researcher Performance

Rank: 6/75

Findings: 3

Award: $2,166.27

๐ŸŒŸ Selected for report: 0

๐Ÿš€ Solo Findings: 0

Findings Information

๐ŸŒŸ Selected for report: Lambda

Also found by: Respx, Ruhum

Labels

bug
duplicate
2 (Med Risk)

Awards

2078.8043 USDC - $2,078.80

External Links

Lines of code

https://github.com/code-423n4/2022-07-axelar/blob/9c4c44b94cddbd48b9baae30051a4e13cbe39539/contracts/auth/AxelarAuthWeighted.sol#L76 https://github.com/code-423n4/2022-07-axelar/blob/9c4c44b94cddbd48b9baae30051a4e13cbe39539/contracts/auth/AxelarAuthWeighted.sol#L36

Vulnerability details

Impact

It is possible to transfer operatorship to the same operators by simply doubling the values of the newWeights array and newThreshold value. This could be used by newly appointed operators to invalidate all previous operators and thus invalidate the intended functionality of AxelarAuthWeighted.OLD_KEY_RETENTION. It is possible operators might not do this maliciously: they might be testing or reconfiguring, unaware of the impact on the older commands. UPDATE: It has been explained on the Discord that "the operator address for a given epoch is derived from the validator key along with a nonce that is unique for each operator epoch and chain.". Given that, operators would be able to transfer operatorship to themselves indefinitely and would not need to even change weights.

Proof of Concept

https://github.com/code-423n4/2022-07-axelar/blob/9c4c44b94cddbd48b9baae30051a4e13cbe39539/contracts/auth/AxelarAuthWeighted.sol#L76 https://github.com/code-423n4/2022-07-axelar/blob/9c4c44b94cddbd48b9baae30051a4e13cbe39539/contracts/auth/AxelarAuthWeighted.sol#L36

Maintain a state variable of the oldest allowable epoch, and create a command to update it.

#0 - re1ro

2022-08-05T06:37:18Z

Duplicate of #98

#1 - GalloDaSballo

2022-09-04T19:26:57Z

Dup of #19

Dangerous comment could break functionality

https://github.com/code-423n4/2022-07-axelar/blob/9c4c44b94cddbd48b9baae30051a4e13cbe39539/contracts/deposit-service/DepositBase.sol#L12 The comment on line 12 of DepositBase says that the relevant variables are immutable for gas optimisation. In fact, the immutable keyword is essential for functionality. The contract ReceiverImplementation inherits from DepositBase and is the target of delegatecall() from DepositReceiver. The functions called in these delegatecalls use the value of the variable gateway throughout. This variable would not be set in the storage of the calling DepositReceiver and it is only accessible because immutable variables are hardocded into the contract code by the constructor. That is why gateway is accessible in a delegatecall. If gateway were no longer immutable, it would take on the value in the corresponding storage slot of DepositReceiver.

Comment refers to ownership without ownership functionality

https://github.com/code-423n4/2022-07-axelar/blob/9c4c44b94cddbd48b9baae30051a4e13cbe39539/contracts/deposit-service/DepositBase.sol#L10 https://github.com/code-423n4/2022-07-axelar/blob/9c4c44b94cddbd48b9baae30051a4e13cbe39539/contracts/deposit-service/ReceiverImplementation.sol#L10 These comments refer to the contracts being "owned". Neither contract has any ownable functionality. Also, as they are used as targets for a delegatecall, the deployng account is not significant either.

AxelarAuthWeighted - Pointless Test

https://github.com/code-423n4/2022-07-axelar/blob/9c4c44b94cddbd48b9baae30051a4e13cbe39539/contracts/auth/AxelarAuthWeighted.sol#L76 It has been explained on the Discord that "the operator address for a given epoch is derived from the validator key along with a nonce that is unique for each operator epoch and chain.". Given that, this test would not be able to detect if the operators were the same.

#0 - re1ro

2022-08-05T06:34:42Z

1

Good spot. immutable is doing much more than just gas saving

2

Good spot. Will correct that

3

We still have the duplicate operators hash check in the AxelarAuthWeighted. So the unit test just covering that functionality. Despite the fact that such duplicate addresses should never appear in practice

#1 - GalloDaSballo

2022-09-01T00:50:33Z

##ย Dangerous comment could break functionality Neat report -> L

Comment refers to ownership without ownership functionality

R

AxelarAuthWeighted - Pointless Test

Disagree as the test increases coverage (try getting anything to 100% coverage and you'll agree with me it's hard to write a pointless test)

1 L 1 R

Good unique perspective, just needs more finds

Commands in string form require unnecessary processing

https://github.com/code-423n4/2022-07-axelar/blob/9c4c44b94cddbd48b9baae30051a4e13cbe39539/contracts/AxelarGateway.sol#L271-L316 Because commands is an array of strings, the commands are being processed on line 298 into a bytes32 variable for easy comparison with constants. Functionally, however, these selectors are simply being used to switch between 6 options. It would be more gas efficient to submit the commands as uint variables or, at the very least, to submit them processed into bytes32 form. If necessary, it would be possible to have a function available for operators which converts the command strings to these uints. That function could be called in a gasless call when composing the transaction which calls execute().

Return a constant instead of keccak of a string literal

https://github.com/code-423n4/2022-07-axelar/blob/9c4c44b94cddbd48b9baae30051a4e13cbe39539/contracts/deposit-service/AxelarDepositService.sol#L242 https://github.com/code-423n4/2022-07-axelar/blob/9c4c44b94cddbd48b9baae30051a4e13cbe39539/contracts/deposit-service/AxelarDepositServiceProxy.sol#L9 https://github.com/code-423n4/2022-07-axelar/blob/9c4c44b94cddbd48b9baae30051a4e13cbe39539/contracts/gas-service/AxelarGasService.sol#L181 https://github.com/code-423n4/2022-07-axelar/blob/9c4c44b94cddbd48b9baae30051a4e13cbe39539/contracts/gas-service/AxelarGasServiceProxy.sol#L10 https://github.com/code-423n4/2022-07-axelar/blob/9c4c44b94cddbd48b9baae30051a4e13cbe39539/xc20/contracts/XC20Wrapper.sol#L41 My gas tests showed that using a constant is more gas efficient than these keccak256() calls.

contract KeccakTest { bytes32 public constant myconstant = keccak256('axelar-deposit-service'); function contractId() public pure returns (bytes32) { return keccak256('axelar-deposit-service'); } function contractId2() public pure returns (bytes32) { return myconstant; } }

#0 - re1ro

2022-08-05T04:13:06Z

Ack. We prefer this approach for simplicity of verification. This is called on only upgrades

#1 - GalloDaSballo

2022-08-23T01:04:17Z

50 gas per command

5 * 30 gas per keccak 150

200 gas saved

#2 - GalloDaSballo

2022-08-23T01:05:20Z

Would recommend always showing the result (image or copy paste of terminal) Also note that the benchmark is setup in a way that is biased, a second function in the same contract will cause overhead due to the way the dispatch for contract calls is done in solidity.

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax ยฉ 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter