Skip to content

Commit

Permalink
Merge pull request #97 from 1inch/feature/oz-500
Browse files Browse the repository at this point in the history
[SC-989][SC-990] Bump @OpenZeppelin to version 5.0.0
  • Loading branch information
ZumZoom authored Nov 14, 2023
2 parents dd98d57 + fbac933 commit 8bf9ccb
Show file tree
Hide file tree
Showing 15 changed files with 75 additions and 59 deletions.
22 changes: 11 additions & 11 deletions .solcover.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@ module.exports = {
yul: true,
yulDetails: {
optimizerSteps:
'dhfoDgvlfnTUtnIf' + // None of these can make stack problems worse
'dhfoDgvlfnTUtnIf' + // None of these can make stack problems worse
'[' +
'xa[r]EscLM' + // Turn into SSA and simplify
'cCTUtTOntnfDIl' + // Perform structural simplification
'Lcl' + // Simplify again
'Vcl [j]' + // Reverse SSA
'xa[r]EscLM' + // Turn into SSA and simplify
'cCTUtTOntnfDIl' + // Perform structural simplification
'Lcl' + // Simplify again
'Vcl [j]' + // Reverse SSA

// should have good 'compilability' property here.

'Tpel' + // Run functional expression inliner
'xa[rl]' + // Prune a bit more in SSA
'xa[r]cL' + // Turn into SSA again and simplify
// 'gvif' + // Run full inliner
'CTUca[r]LSsTFOtfDnca[r]Ilc' + // SSA plus simplify
'Tpel' + // Run functional expression inliner
'xa[rl]' + // Prune a bit more in SSA
'xa[r]cL' + // Turn into SSA again and simplify
'gvf' + // Run full inliner
'CTUca[r]LSsTFOtfDnca[r]Ilc' + // SSA plus simplify
']' +
'jml[jl] VcTOcl jml', // Make source short and pretty
'jml[jl] VcTOcl jml : fDnTOcm', // Make source short and pretty
},
},
skipFiles: [
Expand Down
14 changes: 7 additions & 7 deletions contracts/libraries/SafeERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol";
import "../interfaces/IDaiLikePermit.sol";
import "../interfaces/IPermit2.sol";
import "../interfaces/IWETH.sol";
Expand Down Expand Up @@ -59,7 +59,7 @@ library SafeERC20 {

/**
* @notice Attempts to safely transfer tokens from one address to another.
* @dev If permit2 is true, uses the Permit2 standard; otherwise uses the standard ERC20 transferFrom.
* @dev If permit2 is true, uses the Permit2 standard; otherwise uses the standard ERC20 transferFrom.
* Either requires `true` in return data, or requires target to be smart-contract and empty return data.
* @param token The IERC20 token contract from which the tokens will be transferred.
* @param from The address from which the tokens will be transferred.
Expand Down Expand Up @@ -238,7 +238,7 @@ library SafeERC20 {
}

/**
* @notice Attempts to execute the `permit` function on the provided token with custom owner and spender parameters.
* @notice Attempts to execute the `permit` function on the provided token with custom owner and spender parameters.
* Permit type is determined automatically based on permit calldata (IERC20Permit, IDaiLikePermit, and IPermit2).
* @dev Wraps `tryPermit` function and forwards revert reason if permit fails.
* @param token The IERC20 token to execute the permit function on.
Expand All @@ -265,9 +265,9 @@ library SafeERC20 {
* @notice The function attempts to call the permit function on a given ERC20 token.
* @dev The function is designed to support a variety of permit functions, namely: IERC20Permit, IDaiLikePermit, and IPermit2.
* It accommodates both Compact and Full formats of these permit types.
* Please note, it is expected that the `expiration` parameter for the compact Permit2 and the `deadline` parameter
* Please note, it is expected that the `expiration` parameter for the compact Permit2 and the `deadline` parameter
* for the compact Permit are to be incremented by one before invoking this function. This approach is motivated by
* gas efficiency considerations; as the unlimited expiration period is likely to be the most common scenario, and
* gas efficiency considerations; as the unlimited expiration period is likely to be the most common scenario, and
* zeros are cheaper to pass in terms of gas cost. Thus, callers should increment the expiration or deadline by one
* before invocation for optimized performance.
* @param token The address of the ERC20 token on which to call the permit function.
Expand Down Expand Up @@ -349,7 +349,7 @@ library SafeERC20 {
mstore(add(ptr, 0x24), token) // store token

calldatacopy(add(ptr, 0x50), permit.offset, 0x14) // store amount = copy permit.offset 0x00..0x13
// and(0xffffffffffff, ...) - conversion to uint48
// and(0xffffffffffff, ...) - conversion to uint48
mstore(add(ptr, 0x64), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x14))), 1))) // store expiration = ((permit.offset 0x14..0x17 - 1) & 0xffffffffffff)
mstore(add(ptr, 0x84), shr(224, calldataload(add(permit.offset, 0x18)))) // store nonce = copy permit.offset 0x18..0x1b
mstore(add(ptr, 0xa4), spender) // store spender
Expand Down Expand Up @@ -383,7 +383,7 @@ library SafeERC20 {
* @param selector The function signature that is to be called on the token contract.
* @param to The address to which the token amount will be transferred.
* @param amount The token amount to be transferred.
* @return success A boolean indicating if the call was successful. Returns 'true' on success and 'false' on failure.
* @return success A boolean indicating if the call was successful. Returns 'true' on success and 'false' on failure.
* In case of success but no returned data, validates that the contract code exists.
* In case of returned data, ensures that it's a boolean `true`.
*/
Expand Down
2 changes: 1 addition & 1 deletion contracts/mocks/ERC20PermitMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
import "./TokenMock.sol";

contract ERC20PermitMock is ERC20Permit, TokenMock {
Expand Down
4 changes: 2 additions & 2 deletions contracts/mocks/TokenCustomDecimalsMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";

contract TokenCustomDecimalsMock is ERC20Permit, Ownable {
uint8 internal immutable _decimals;
Expand All @@ -13,7 +13,7 @@ contract TokenCustomDecimalsMock is ERC20Permit, Ownable {
string memory symbol,
uint256 amount,
uint8 decimals_
) ERC20(name, symbol) ERC20Permit(name) {
) ERC20(name, symbol) ERC20Permit(name) Ownable(msg.sender) {
_mint(msg.sender, amount);
_decimals = decimals_;
}
Expand Down
2 changes: 1 addition & 1 deletion contracts/mocks/TokenMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract TokenMock is ERC20, Ownable {
// solhint-disable-next-line no-empty-blocks
constructor(string memory name, string memory symbol) ERC20(name, symbol) {}
constructor(string memory name, string memory symbol) ERC20(name, symbol) Ownable(msg.sender) {}

function mint(address account, uint256 amount) external onlyOwner {
_mint(account, amount);
Expand Down
2 changes: 1 addition & 1 deletion contracts/tests/mocks/DaiLikePermitMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";

contract DaiLikePermitMock is ERC20Permit {
// bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)");
Expand Down
4 changes: 1 addition & 3 deletions contracts/tests/mocks/ERC1271WalletMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ import "@openzeppelin/contracts/interfaces/IERC1271.sol";
import "../../libraries/ECDSA.sol";

contract ERC1271WalletMock is Ownable, IERC1271 {
constructor(address originalOwner) {
transferOwnership(originalOwner);
}
constructor(address originalOwner) Ownable(originalOwner) {} // solhint-disable-line no-empty-blocks

function isValidSignature(bytes32 hash, bytes calldata signature) public view override returns (bytes4 magicValue) {
return ECDSA.recover(hash, signature) == owner() ? this.isValidSignature.selector : bytes4(0);
Expand Down
2 changes: 1 addition & 1 deletion contracts/tests/mocks/SafeERC20Helper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
import "../../libraries/SafeERC20.sol";

contract ERC20ReturnFalseMock {
Expand Down
9 changes: 8 additions & 1 deletion hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import '@nomicfoundation/hardhat-verify';
require('solidity-coverage'); // require because no TS typings available
import dotenv from 'dotenv';
import { HardhatUserConfig } from 'hardhat/config';
import { HardhatNetworkUserConfig } from 'hardhat/types';
import networks from './hardhat.networks';

dotenv.config();
Expand All @@ -18,14 +19,20 @@ declare module 'hardhat/types/runtime' {
}
}

function getNetwork(): string {
const index = process.argv.findIndex((arg) => arg === '--network') + 1;
return index !== 0 ? process.argv[index] : 'unknown';
}

const config: HardhatUserConfig = {
solidity: {
version: '0.8.15',
version: '0.8.23',
settings: {
optimizer: {
enabled: true,
runs: 1000000,
},
evmVersion: (networks[getNetwork()] as HardhatNetworkUserConfig)?.hardfork || 'shanghai',
viaIR: true,
},
},
Expand Down
37 changes: 25 additions & 12 deletions hardhat.networks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,41 @@ const networks: NetworksUserConfig = {
},
};

function register(name: string, chainId: number, url?: string, privateKey?: string) {
if (url && privateKey) {
const etherscan: { apiKey: {[key: string]: string}, customChains: [object] } = { apiKey: {}, customChains: [{}] };

function register(name: string, chainId: number, url?: string, privateKey?: string, etherscanNetworkName?: string, etherscanKey?: string, hardfork: string = 'paris') {
if (url && privateKey && etherscanNetworkName && etherscanKey) {
networks[name] = {
url,
chainId,
accounts: [privateKey],
hardfork,
};
etherscan.apiKey[etherscanNetworkName] = etherscanKey;
console.log(`Network '${name}' registered`);
} else {
console.log(`Network '${name}' not registered`);
}
}

register('mainnet', 1, process.env.MAINNET_RPC_URL, process.env.MAINNET_PRIVATE_KEY);
register('bsc', 56, process.env.BSC_RPC_URL, process.env.BSC_PRIVATE_KEY);
register('kovan', 42, process.env.KOVAN_RPC_URL, process.env.KOVAN_PRIVATE_KEY);
register('optimistic', 10, process.env.OPTIMISTIC_RPC_URL, process.env.OPTIMISTIC_PRIVATE_KEY);
register('kovan-optimistic', 69, process.env.KOVAN_OPTIMISTIC_RPC_URL, process.env.KOVAN_OPTIMISTIC_PRIVATE_KEY);
register('matic', 137, process.env.MATIC_RPC_URL, process.env.MATIC_PRIVATE_KEY);
register('arbitrum', 42161, process.env.ARBITRUM_RPC_URL, process.env.ARBITRUM_PRIVATE_KEY);
register('ropsten', 3, process.env.ROPSTEN_RPC_URL, process.env.ROPSTEN_PRIVATE_KEY);
register('xdai', 100, process.env.XDAI_RPC_URL, process.env.XDAI_PRIVATE_KEY);
register('avax', 43114, process.env.AVAX_RPC_URL, process.env.AVAX_PRIVATE_KEY);
function registerCustom(name: string, chainId: number, url?: string, privateKey?: string, etherscanKey?: string, apiURL?: string, browserURL?: string, hardfork = 'paris') {
if (url && privateKey && etherscanKey) {
register(name, chainId, hardfork, url, privateKey, name, etherscanKey);
etherscan.customChains.push({ network: name, chainId, urls: { apiURL, browserURL } });
}
}

register('mainnet', 1, process.env.MAINNET_RPC_URL, process.env.MAINNET_PRIVATE_KEY, 'mainnet', process.env.MAINNET_ETHERSCAN_KEY, 'shanghai');
register('bsc', 56, process.env.BSC_RPC_URL, process.env.BSC_PRIVATE_KEY, 'bsc', process.env.BSC_ETHERSCAN_KEY);
register('kovan', 42, process.env.KOVAN_RPC_URL, process.env.KOVAN_PRIVATE_KEY, 'kovan', process.env.KOVAN_ETHERSCAN_KEY);
register('optimistic', 10, process.env.OPTIMISTIC_RPC_URL, process.env.OPTIMISTIC_PRIVATE_KEY, 'optimisticEthereum', process.env.OPTIMISTIC_ETHERSCAN_KEY);
register('matic', 137, process.env.MATIC_RPC_URL, process.env.MATIC_PRIVATE_KEY, 'polygon', process.env.MATIC_ETHERSCAN_KEY);
register('arbitrum', 42161, process.env.ARBITRUM_RPC_URL, process.env.ARBITRUM_PRIVATE_KEY, 'arbitrumOne', process.env.ARBITRUM_ETHERSCAN_KEY);
register('xdai', 100, process.env.XDAI_RPC_URL, process.env.XDAI_PRIVATE_KEY, 'gnosis', process.env.XDAI_ETHERSCAN_KEY);
register('avax', 43114, process.env.AVAX_RPC_URL, process.env.AVAX_PRIVATE_KEY, 'avalanche', process.env.AVAX_ETHERSCAN_KEY);
register('fantom', 250, process.env.FANTOM_RPC_URL, process.env.FANTOM_PRIVATE_KEY, 'opera', process.env.FANTOM_ETHERSCAN_KEY);
register('aurora', 1313161554, process.env.AURORA_RPC_URL, process.env.AURORA_PRIVATE_KEY, 'aurora', process.env.AURORA_ETHERSCAN_KEY);
register('base', 8453, process.env.BASE_RPC_URL, process.env.BASE_PRIVATE_KEY, 'base', process.env.BASE_ETHERSCAN_KEY);
registerCustom('klaytn', 8217, process.env.KLAYTN_RPC_URL, process.env.KLAYTN_PRIVATE_KEY, process.env.KLAYTN_ETHERSCAN_KEY, 'https://scope.klaytn.com/', 'https://scope.klaytn.com/');

export default networks;
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@1inch/solidity-utils",
"version": "3.2.0",
"version": "3.3.0",
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
"repository": {
Expand Down Expand Up @@ -31,7 +31,7 @@
"@metamask/eth-sig-util": "6.0.0",
"@nomicfoundation/hardhat-ethers": "3.0.3",
"@nomicfoundation/hardhat-network-helpers": "1.0.8",
"@openzeppelin/contracts": "4.9.2",
"@openzeppelin/contracts": "5.0.0",
"@uniswap/permit2-sdk": "1.2.0",
"ethereumjs-util": "7.1.5",
"ethers": "6.6.3",
Expand Down
6 changes: 2 additions & 4 deletions test/Permitable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ describe('Permitable', function () {
const deadline = block ? block.timestamp - 1000 : 1000;

const permit = await getPermit(signer1, erc20PermitMock, '1', chainId, await permitableMock.getAddress(), value.toString(), deadline.toString());
await expect(permitableMock.mockPermit(erc20PermitMock, permit)).to.be.revertedWith('ERC20Permit: expired deadline');
await expect(permitableMock.mockPermit(erc20PermitMock, permit)).to.be.revertedWithCustomError(erc20PermitMock, 'ERC2612ExpiredSignature');
});

it('should not be permitted for IERC20Permit', async function () {
Expand Down Expand Up @@ -100,9 +100,7 @@ describe('Permitable', function () {
s,
]),
);
await expect(permitableMock.mockPermit(erc20PermitMock, permit)).to.be.revertedWith(
'ERC20Permit: invalid signature',
);
await expect(permitableMock.mockPermit(erc20PermitMock, permit)).to.be.revertedWithCustomError(erc20PermitMock, 'ERC2612InvalidSigner');
});

it('should be permitted for IDaiLikePermit', async function () {
Expand Down
4 changes: 2 additions & 2 deletions test/contracts/SafestERC20.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ describe('SafeERC20', function () {
expect(received).to.be.equal(ether('1'));
if (hre.__SOLIDITY_COVERAGE_RUNNING === undefined) {
expect(await countInstructions(ethers.provider, tx.logs[0].transactionHash, ['STATICCALL', 'CALL', 'MSTORE', 'MLOAD', 'SSTORE', 'SLOAD'])).to.be.deep.equal([
0, 1, 6, 3, 1, 2,
0, 1, 6, 1, 1, 2,
]);
}
});
Expand All @@ -313,7 +313,7 @@ describe('SafeERC20', function () {
);
if (hre.__SOLIDITY_COVERAGE_RUNNING === undefined) {
expect(await countInstructions(ethers.provider, tx.hash, ['STATICCALL', 'CALL', 'MSTORE', 'MLOAD', 'SSTORE', 'SLOAD'])).to.be.deep.equal([
0, 0, 1, 1, 0, 1,
0, 0, 1, 0, 0, 1,
]);
}
});
Expand Down
14 changes: 7 additions & 7 deletions test/contracts/StringUtil.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,31 +69,31 @@ describe('StringUtil', function () {

it('Uint 256', () => testGasUint256(uint256TestValue, 834));

it('Uint 256 naive', () => testGasNaiveUint256(uint256TestValue, 16277));
it('Uint 256 naive', () => testGasNaiveUint256(uint256TestValue, 16369));

it('Uint 256 as bytes', () => testGasBytes(uint256TestValue, 716));

it('Uint 256 as bytes naive', () => testGasNaiveBytes(uint256TestValue, 16159));
it('Uint 256 as bytes naive', () => testGasNaiveBytes(uint256TestValue, 16251));

it('Uint 128', () => testGasUint256(uint128TestValue, 834));

it('Uint 128 naive', () => testGasNaiveUint256(uint128TestValue, 16277));
it('Uint 128 naive', () => testGasNaiveUint256(uint128TestValue, 16369));

it('Very long byte array gas', () => testGasBytes(veryLongArray, 1766));

it('Very long byte array gas naive', () => testGasNaiveBytes(veryLongArray, 33286));
it('Very long byte array gas naive', () => testGasNaiveBytes(veryLongArray, 33483));

it('Extremely long byte array gas', () => testGasBytes(extremelyLongArray, 17009));

it('Extremely long byte array gas naive', () => testGasNaiveBytes(extremelyLongArray, 489888));
it('Extremely long byte array gas naive', () => testGasNaiveBytes(extremelyLongArray, 492884));

it('Empty bytes', () => testGasBytes(emptyBytes, 191));

it('Empty bytes naive', () => testGasNaiveBytes(emptyBytes, 499));
it('Empty bytes naive', () => testGasNaiveBytes(emptyBytes, 495));

it('Single byte', () => testGasBytes(singleByte, 716));

it('Single byte naive', () => testGasNaiveBytes(singleByte, 988));
it('Single byte naive', () => testGasNaiveBytes(singleByte, 987));

async function testGasUint256(value: string, expectedGas: number) {
const { stringUtilTest } = await loadFixture(deployStringUtilTest);
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -824,10 +824,10 @@
"@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.1"
"@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.1"

"@openzeppelin/contracts@4.9.2":
version "4.9.2"
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.2.tgz#1cb2d5e4d3360141a17dbc45094a8cad6aac16c1"
integrity sha512-mO+y6JaqXjWeMh9glYVzVu8HYPGknAAnWyxTRhGeckOruyXQMNnlcW6w/Dx9ftLeIQk6N+ZJFuVmTwF7lEIFrg==
"@openzeppelin/contracts@5.0.0":
version "5.0.0"
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.0.0.tgz#ee0e4b4564f101a5c4ee398cd4d73c0bd92b289c"
integrity sha512-bv2sdS6LKqVVMLI5+zqnNrNU/CA+6z6CmwFXm/MzmOPBRSO5reEJN7z0Gbzvs0/bv/MZZXNklubpwy3v2+azsw==

"@pkgjs/parseargs@^0.11.0":
version "0.11.0"
Expand Down

0 comments on commit 8bf9ccb

Please sign in to comment.