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
Rank: 28/75
Findings: 2
Award: $88.39
๐ Selected for report: 0
๐ Solo Findings: 0
๐ Selected for report: oyc_109
Also found by: 0x1f8b, 0x52, 0xNazgul, 0xSmartContract, 0xf15ers, 8olidity, Aymen0909, Bnke0x0, CertoraInc, Chom, CodingNameKiki, Deivitto, Dravee, ElKu, IllIllI, JC, Lambda, Noah3o6, NoamYakov, RedOneN, Respx, ReyAdmirado, Rohan16, Rolezn, Ruhum, Sm4rty, TomJ, Twpony, Waze, Yiko, __141345__, ajtra, apostle0x01, ashiq0x01, asutorufos, bardamu, benbaessler, berndartmueller, bharg4v, bulej93, c3phas, cccz, ch13fd357r0y3r, codexploder, cryptonue, cryptphi, defsec, djxploit, durianSausage, fatherOfBlocks, gogo, hansfriese, horsefacts, ignacio, kyteg, lucacez, mics, rbserver, robee, sashik_eth, simon135, sseefried, tofunmi, xiaoming90
56.5067 USDC - $56.51
Severity: Low
Deprecated in favor of safeIncreaseAllowance() and safeDecreaseAllowance(). If only setting the initial allowance to the value that means infinite, safeIncreaseAllowance() can be used instead
IERC20(wrappedTokenAddress).approve(gateway, amount); https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/AxelarDepositService.sol#L30
IERC20(tokenAddress).approve(gateway, amount); https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/ReceiverImplementation.sol#L38
IERC20(wrappedTokenAddress).approve(gateway, amount); https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/ReceiverImplementation.sol#L64
Consider using safeIncreaseAllowance() / safeDecreaseAllowance() instead.
Severity: Low
Some tokens (like USDT L199) do not work when changing the allowance from an existing non-zero allowance value. They must first be approved by zero and then the actual allowance must be approved.
IERC20(wrappedTokenAddress).approve(gateway, amount); https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/AxelarDepositService.sol#L30
IERC20(tokenAddress).approve(gateway, amount); https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/ReceiverImplementation.sol#L38
IERC20(wrappedTokenAddress).approve(gateway, amount); https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/ReceiverImplementation.sol#L64
Approve with a zero amount first before setting the actual amount.
Severity: Low
function _setImplementation(address newImplementation) internal { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/AxelarGateway.sol#L655
function receiveAndUnwrapNative(address payable refundAddress, address payable recipient) external { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/ReceiverImplementation.sol#L70
Consider adding zero-address checks in the mentioned codebase.
Severity: Low
It is good to add a require() statement that checks the return value of token transfers or to use something like OpenZeppelinโs safeTransfer/safeTransferFrom unless one is sure the given token reverts in case of a failure. Failure to do so will cause silent failures of transfers and affect token accounting in contract.
Reference: This similar medium-severity (https://consensys.net/diligence/audits/2021/01/fei-protocol/#unchecked-return-value-for-iweth-transfer-call) finding from Consensys Diligence Audit of Fei Protocol.
payable(msg.sender).transfer(address(this).balance); https://github.com/code-423n4/2022-07-golom/tree/main/contracts/XC20Wrapper.sol#L63
if (address(this).balance > 0) refundAddress.transfer(address(this).balance); https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/ReceiverImplementation.sol#L23
if (address(this).balance > 0) refundAddress.transfer(address(this).balance); https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/ReceiverImplementation.sol#L51
if (address(this).balance > 0) refundAddress.transfer(address(this).balance); https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/ReceiverImplementation.sol#L71
if (amount > 0) receiver.transfer(amount); https://github.com/code-423n4/2022-07-golom/tree/main/contracts/gas-service/AxelarGasService.sol#L128
receiver.transfer(amount); https://github.com/code-423n4/2022-07-golom/tree/main/contracts/gas-service/AxelarGasService.sol#L144
Consider using safeTransfer/safeTransferFrom or require() consistently.
Severity: Low
If the intention is for the Ether to be used, the function should call another function, otherwise it should revert
receive() external payable {} https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/DepositReceiver.sol#L29
The function should call another function, otherwise it should revert
Severity: Non-Critical
return getUint(_getTokenDailyMintAmountKey(symbol, block.timestamp / 1 days));
https://github.com/code-423n4/2022-07-golom/tree/main/contracts/AxelarGateway.sol#L157
_setUint(_getTokenDailyMintAmountKey(symbol, block.timestamp / 1 days), amount);
https://github.com/code-423n4/2022-07-golom/tree/main/contracts/AxelarGateway.sol#L615
Severity: Non-Critical
Each event should use three indexed fields if there are three or more fields. In addition, each event should have at least one indexed fields to allow easier filtering of logs.
event OperatorshipTransferred(address[] newOperators, uint256[] newWeights, uint256 newThreshold); https://github.com/code-423n4/2022-07-golom/tree/main/contracts/interfaces/IAxelarAuthWeighted.sol#L14
event GasPaidForContractCall( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, address gasToken, uint256 gasFeeAmount, address refundAddress ); https://github.com/code-423n4/2022-07-golom/tree/main/contracts/interfaces/IAxelarGasService.sol#L13
event GasPaidForContractCallWithToken( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, string symbol, uint256 amount, address gasToken, uint256 gasFeeAmount, address refundAddress ); https://github.com/code-423n4/2022-07-golom/tree/main/contracts/interfaces/IAxelarGasService.sol#L23
event NativeGasPaidForContractCall( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, uint256 gasFeeAmount, address refundAddress ); https://github.com/code-423n4/2022-07-golom/tree/main/contracts/interfaces/IAxelarGasService.sol#L35
event NativeGasPaidForContractCallWithToken( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, string symbol, uint256 amount, uint256 gasFeeAmount, address refundAddress ); https://github.com/code-423n4/2022-07-golom/tree/main/contracts/interfaces/IAxelarGasService.sol#L44
event GasAdded(bytes32 indexed txHash, uint256 indexed logIndex, address gasToken, uint256 gasFeeAmount, address refundAddress); https://github.com/code-423n4/2022-07-golom/tree/main/contracts/interfaces/IAxelarGasService.sol#L55
event NativeGasAdded(bytes32 indexed txHash, uint256 indexed logIndex, uint256 gasFeeAmount, address refundAddress); https://github.com/code-423n4/2022-07-golom/tree/main/contracts/interfaces/IAxelarGasService.sol#L57
Severity: Non-Critical
Use a solidity version of at least 0.8.4 to get bytes.concat() instead of abi.encodePacked(<bytes>,<bytes>) Use a solidity version of at least 0.8.12 to get string.concat() instead of abi.encodePacked(<str>,<str>) Use a solidity version of at least 0.8.13 to get the ability to use using for with a list of free functions
Found old version 0.8.9 of Solidity https://github.com/code-423n4/2022-07-golom/tree/main/contracts/AxelarGateway.sol#L3
Found old version 0.8.9 of Solidity https://github.com/code-423n4/2022-07-golom/tree/main/contracts/XC20Wrapper.sol#L3
Found old version 0.8.9 of Solidity https://github.com/code-423n4/2022-07-golom/tree/main/contracts/auth/AxelarAuthWeighted.sol#L3
Found old version 0.8.9 of Solidity https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/AxelarDepositService.sol#L3
Found old version 0.8.9 of Solidity https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/AxelarDepositServiceProxy.sol#L3
Found old version 0.8.9 of Solidity https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/DepositBase.sol#L3
Found old version 0.8.9 of Solidity https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/DepositReceiver.sol#L3
Found old version 0.8.9 of Solidity https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/ReceiverImplementation.sol#L3
Found old version 0.8.9 of Solidity https://github.com/code-423n4/2022-07-golom/tree/main/contracts/gas-service/AxelarGasService.sol#L3
Found old version 0.8.9 of Solidity https://github.com/code-423n4/2022-07-golom/tree/main/contracts/gas-service/AxelarGasServiceProxy.sol#L3
Found old version 0.8.9 of Solidity https://github.com/code-423n4/2022-07-golom/tree/main/contracts/interfaces/IAxelarAuth.sol#L3
Found old version 0.8.9 of Solidity https://github.com/code-423n4/2022-07-golom/tree/main/contracts/interfaces/IAxelarAuthWeighted.sol#L3
Found old version 0.8.9 of Solidity https://github.com/code-423n4/2022-07-golom/tree/main/contracts/interfaces/IAxelarDepositService.sol#L3
Found old version 0.8.9 of Solidity https://github.com/code-423n4/2022-07-golom/tree/main/contracts/interfaces/IAxelarGasService.sol#L3
Found old version 0.8.9 of Solidity https://github.com/code-423n4/2022-07-golom/tree/main/contracts/interfaces/IDepositBase.sol#L3
Consider updating to a more recent solidity version.
#0 - re1ro
2022-08-04T23:28:36Z
Sorry links are broken
Invalid majority of existing ERC20 tokens support only approve
Acknowledged but not applicable. The initial allowance is always 0 and we spend all the approved allowance and it becomes 0 again.
Valid
Invalid, those are native ether transfer, not ECR20
Invalid. Receive function is needed to receive ether from WETH contract. And that ether is taken care of.
Invalid. 1 day
is a pretty explanatory system constant.
Invalid. You can't index strings without loosing data in them. Other fields are irrelevant for indexing.
We decided not using latest version of the compiler for security reasons. There might be some bugs that will take time to be uncovered. 0.8.9
is suiting us perfectly
#1 - GalloDaSballo
2022-09-04T21:14:06Z
Disputed as the code uses approve properly (from 0 to non-zero)
Same as 1
NC
L
L
Rest I'm skipping as the report is clearly product of automation, and all links are broken meaning the Warden most likely spent less time than me Judging.
If scoring was up I'd give this one below 50 as the advice worth less than the time spent reading it
๐ Selected for report: IllIllI
Also found by: 0x1f8b, 0xNazgul, 0xsam, 8olidity, Aymen0909, Bnke0x0, Chom, CodingNameKiki, Deivitto, Dravee, ElKu, Fitraldys, JC, Lambda, MiloTruck, Noah3o6, NoamYakov, RedOneN, Respx, ReyAdmirado, Rohan16, Rolezn, Ruhum, Sm4rty, TomJ, Tomio, Waze, __141345__, a12jmx, ajtra, ak1, apostle0x01, asutorufos, benbaessler, bharg4v, bulej93, c3phas, defsec, djxploit, durianSausage, erictee, fatherOfBlocks, gerdusx, gogo, kyteg, lucacez, medikko, mics, owenthurm, oyc_109, rbserver, robee, sashik_eth, simon135, tofunmi
31.8812 USDC - $31.88
Severity: Gas Optimizations
return keccak256(abi.encode(PREFIX_CONTRACT_CALL_APPROVED, commandId, sourceChain, sourceAddress, contractAddress, payloadHash)); https://github.com/code-423n4/2022-07-golom/tree/main/contracts/AxelarGateway.sol#L566
abi.encode( https://github.com/code-423n4/2022-07-golom/tree/main/contracts/AxelarGateway.sol#L580
bytes32 operatorsHash = keccak256(abi.encode(operators, weights, threshold)); https://github.com/code-423n4/2022-07-golom/tree/main/contracts/auth/AxelarAuthWeighted.sol#L32
Severity: Gas Optimizations
The overheads outlined below are PER LOOP, excluding the first loop
storage arrays incur a Gwarmaccess (100 gas) memory arrays use MLOAD (3 gas) calldata arrays use CALLDATALOAD (3 gas)
Caching the length changes each of these to a DUP<N> (3 gas), and gets rid of the extra DUP<N> needed to store the stack offset
for (uint256 i = 0; i < symbols.length; i++) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/AxelarGateway.sol#L207
for (uint256 i = 0; i < signatures.length; ++i) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/auth/AxelarAuthWeighted.sol#L98
for (uint256 i; i < accounts.length - 1; ++i) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/auth/AxelarAuthWeighted.sol#L116
for (uint256 i; i < refundTokens.length; i++) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/AxelarDepositService.sol#L114
for (uint256 i; i < refundTokens.length; i++) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/AxelarDepositService.sol#L168
for (uint256 i; i < refundTokens.length; i++) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/AxelarDepositService.sol#L204
for (uint256 i; i < tokens.length; i++) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/gas-service/AxelarGasService.sol#L123
Severity: Gas Optimizations
The code should be refactored such that they no longer exist, or the block should do something useful, such as emitting an event or reverting. If the contract is meant to be extended, the contract should be abstract and the function signatures be added without any default implementation. If the block is an empty if-statement block to avoid doing subsequent checks in the else-if/else conditions, the else-if/else conditions should be nested under the negation of the if-statement, because they involve different classes of checks, which may lead to the introduction of errors when the code is later modified (if(x){}else if(y){...}else{...} => if(!x){if(y){...}else{...}})
for (; operatorIndex < operatorsLength && signer != operators[operatorIndex]; ++operatorIndex) {} https://github.com/code-423n4/2022-07-golom/tree/main/contracts/auth/AxelarAuthWeighted.sol#L101
receive() external payable override {} https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/AxelarDepositServiceProxy.sol#L13
Severity: Gas Optimizations
Saves 6 gas per loop
for (uint256 i = 0; i < symbols.length; i++) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/AxelarGateway.sol#L207
for (uint256 i; i < refundTokens.length; i++) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/AxelarDepositService.sol#L114
for (uint256 i; i < refundTokens.length; i++) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/AxelarDepositService.sol#L168
for (uint256 i; i < refundTokens.length; i++) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/AxelarDepositService.sol#L204
for (uint256 i; i < tokens.length; i++) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/gas-service/AxelarGasService.sol#L123
For example, use ++i instead of i++
Severity: Gas Optimizations
for (uint256 i = 0; i < symbols.length; i++) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/AxelarGateway.sol#L207
for (uint256 i = 0; i < weightsLength; ++i) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/auth/AxelarAuthWeighted.sol#L69
for (uint256 i = 0; i < signatures.length; ++i) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/auth/AxelarAuthWeighted.sol#L98
Severity: Gas Optimizations
Saves a storage slot for the mapping. Depending on the circumstances and sizes of types, can avoid a Gsset (20000 gas) per mapping combined. Reads and subsequent writes can also be cheaper when a function requires both values and they both fit in the same storage slot.
mapping(address => address) public wrapped; mapping(address => address) public unwrapped;
https://github.com/code-423n4/2022-07-golom/tree/main/contracts/XC20Wrapper.sol#L20
Severity: Gas Optimizations
totalWeight += newWeights[i]; https://github.com/code-423n4/2022-07-golom/tree/main/contracts/auth/AxelarAuthWeighted.sol#L70
weight += weights[operatorIndex]; https://github.com/code-423n4/2022-07-golom/tree/main/contracts/auth/AxelarAuthWeighted.sol#L105
Severity: Gas Optimizations
The unchecked keyword is new in solidity version 0.8.0, so this only applies to that version or higher, which these instances are. This saves 30-40 gas PER LOOP
for (uint256 i; i < adminCount; ++i) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/AxelarGateway.sol#L195
for (uint256 i = 0; i < symbols.length; i++) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/AxelarGateway.sol#L207
for (uint256 i; i < commandsLength; ++i) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/AxelarGateway.sol#L292
for (uint256 i = 0; i < weightsLength; ++i) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/auth/AxelarAuthWeighted.sol#L69
for (uint256 i = 0; i < signatures.length; ++i) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/auth/AxelarAuthWeighted.sol#L98
for (; operatorIndex < operatorsLength && signer != operators[operatorIndex]; ++operatorIndex) {} https://github.com/code-423n4/2022-07-golom/tree/main/contracts/auth/AxelarAuthWeighted.sol#L101
for (uint256 i = 0; i < signatures.length; ++i) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/auth/AxelarAuthWeighted.sol#L98
for (; operatorIndex < operatorsLength && signer != operators[operatorIndex]; ++operatorIndex) {} https://github.com/code-423n4/2022-07-golom/tree/main/contracts/auth/AxelarAuthWeighted.sol#L101
for (uint256 i; i < accounts.length - 1; ++i) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/auth/AxelarAuthWeighted.sol#L116
for (uint256 i; i < refundTokens.length; i++) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/AxelarDepositService.sol#L114
for (uint256 i; i < refundTokens.length; i++) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/AxelarDepositService.sol#L168
for (uint256 i; i < refundTokens.length; i++) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/deposit-service/AxelarDepositService.sol#L204
for (uint256 i; i < tokens.length; i++) { https://github.com/code-423n4/2022-07-golom/tree/main/contracts/gas-service/AxelarGasService.sol#L123
#0 - re1ro
2022-08-04T23:16:15Z
abi.encodePacked
is not secure for cryptographic hashing. Example
abi.encodePacked('ab','c') == abi.encodePacked('a', 'bc')
Yes
Not applicable. This loop is written in the most efficient way. We just need contract to be able to receive ether from WETH contact. We don't need to do anything in the receive function
Yes
Yes
Not applicable. It's a bidirectional mapping A -> B, and B -> A
Yes
Yes
#1 - GalloDaSballo
2022-08-23T01:08:46Z
Doesn't apply, however there could be a way to do it, but you need to submit a coded POC for this type of changes (and you'll get a ton of points btw)
Rest will save less than 300 gas