code4rena-2022-08-nounsdao-n01
[N‑01] public functions not called by the contract should be declared external instead
Summary
동일 컨트랙트에서 해당 함수를 호출하지 않는다면 public 대신 external로 선언하여 가스를 절약할 수 있다.
Keyword
solidity, function visibility, gas optimization
Vulnerability
- contracts/governance/NounsDAOLogicV1.sol#L174-L180
- contracts/governance/NounsDAOLogicV2.sol#L184-L190
File: contracts/governance/NounsDAOLogicV1.sol
174 function propose(
175 address[] memory targets,
176 uint256[] memory values,
177 string[] memory signatures,
178 bytes[] memory calldatas,
179 string memory description
180: ) public returns (uint256) {
649 function _burnVetoPower() public {
650 // Check caller is pendingAdmin and pendingAdmin ≠ address(0)
651: require(msg.sender == vetoer, 'NounsDAO::_burnVetoPower: vetoer only');
660: function proposalThreshold() public view returns (uint256) {
668: function quorumVotes() public view returns (uint256) {File: contracts/governance/NounsDAOLogicV2.sol
184 function propose(
185 address[] memory targets,
186 uint256[] memory values,
187 string[] memory signatures,
188 bytes[] memory calldatas,
189 string memory description
190: ) public returns (uint256) {
851 function _burnVetoPower() public {
852 // Check caller is pendingAdmin and pendingAdmin ≠ address(0)
853: require(msg.sender == vetoer, 'NounsDAO::_burnVetoPower: vetoer only');
862: function proposalThreshold() public view returns (uint256) {
1002: function maxQuorumVotes() public view returns (uint256) {external의 경우 public 보다 Gas를 덜 사용한다. 왜냐하면 public의 경우 배열을 메모리에 즉시 복사하지만, external은 calldata에서 직접 읽을 수 있기 때문이다.
단, external의 경우 this.f() 식으로 동일 컨트랙트의 다른 함수에서 호출할 수 없다는 단점이 있다. 동일 컨트랙트에서 해당 함수를 호출하지 않는다면 public 대신 external로 선언하여 가스를 절약할 수 있다.
Impact
함수 호출 시 불필요하게 Gas를 소모한다.
Mitigation
동일 컨트랙트 내부에서 호출하지 않을 함수 visibility를 public → external 로 변경한다.
Memo
왜 Gas로 판정되지 않고 Non-Critical로 분류되었는지 모르겠다.
tags: bughunting, nouns dao, smart contract, solidity, solidity function visibility, gas optimization, solidity public, solidity external, severity none