Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release/v1.4.1 2 #8

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ ETHERSCAN_API_KEY=""
ERC4337_TEST_BUNDLER_URL=
ERC4337_TEST_NODE_URL=
ERC4337_TEST_SINGLETON_ADDRESS=
ERC4337_TEST_SAFE_FACTORY_ADDRESS=
ERC4337_TEST_SAFE_FACTORY_ADDRESS=
# Sets hardhat chain id. In general, you don't need this, it's only used for testing the SafeToL2Setup contract.
HARDHAT_CHAIN_ID=31337
150 changes: 72 additions & 78 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,81 +1,75 @@
name: safe-contracts
on: [ push, pull_request ]
on: [push, pull_request]

jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 16.7.0
- uses: actions/cache@v2
with:
path: "**/node_modules"
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
- run: yarn --frozen-lockfile
- run: yarn build
- run: yarn coverage
- name: Coveralls
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 16.7.0
- uses: actions/cache@v2
with:
path: "**/node_modules"
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
- run: yarn --frozen-lockfile
- run: yarn lint:sol
tests-other:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
contract-name: ["SafeL2"]
env:
SAFE_CONTRACT_UNDER_TEST: ${{ matrix.contract-name }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 16.7.0
- uses: actions/cache@v2
with:
path: "**/node_modules"
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
- run: yarn --frozen-lockfile
- run: yarn build
- run: yarn coverage
- name: Coveralls
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
benchmarks:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
solidity: ["0.7.6", "0.8.2"]
include:
- solidity: "0.8.2"
settings: '{"viaIR":true,"optimizer":{"enabled":true,"runs":10000}}'
env:
SOLIDITY_VERSION: ${{ matrix.solidity }}
SOLIDITY_SETTINGS: ${{ matrix.settings }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 16.7.0
- uses: actions/cache@v2
with:
path: "**/node_modules"
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
- run: (yarn --frozen-lockfile && yarn build && yarn hardhat codesize --contractname Safe && yarn benchmark) || echo "Benchmark failed"
tests:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
contract-name: ["Safe", "SafeL2"]
env:
SAFE_CONTRACT_UNDER_TEST: ${{ matrix.contract-name }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION }}
cache: "yarn"
- run: yarn --frozen-lockfile
- run: yarn build
- run: yarn coverage
- name: Send coverage to Coveralls (parallel)
uses: coverallsapp/github-action@v2
with:
parallel: true
flag-name: run-$
github-token: ${{ secrets.GITHUB_TOKEN }}

finish:
runs-on: ubuntu-latest
needs: tests
if: ${{ always() }}
steps:
- name: Coveralls Finished
uses: coverallsapp/github-action@v2
with:
parallel-finished: true
carryforward: "run-Safe,run-SafeL2"

lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 16.7.0
- uses: actions/cache@v2
with:
path: "**/node_modules"
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
- run: yarn --frozen-lockfile
- run: yarn lint:sol

benchmarks:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
solidity: ["0.7.6", "0.8.2"]
include:
- solidity: "0.8.2"
settings: '{"viaIR":true,"optimizer":{"enabled":true,"runs":10000}}'
env:
SOLIDITY_VERSION: ${{ matrix.solidity }}
SOLIDITY_SETTINGS: ${{ matrix.settings }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 16.7.0
- uses: actions/cache@v2
with:
path: "**/node_modules"
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
- run: (yarn --frozen-lockfile && yarn build && yarn hardhat codesize --contractname Safe && yarn benchmark) || echo "Benchmark failed"
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ To add support for a new network follow the steps of the ``Deploy`` section and

> :warning: **Make sure to use the correct commit when deploying the contracts.** Any change (even comments) within the contract files will result in different addresses. The tagged versions that are used by the Safe team can be found in the [releases](https://github.com/safe-global/safe-contracts/releases).

> **Current version:** The latest release is [v1.3.0-libs.0](https://github.com/safe-global/safe-contracts/tree/v1.3.0-libs.0) on the commit [767ef36](https://github.com/safe-global/safe-contracts/commit/767ef36bba88bdbc0c9fe3708a4290cabef4c376)
> **Current version:** The latest release is [v1.4.1-1](https://github.com/safe-global/safe-contracts/tree/v1.4.1-1)

This will deploy the contracts deterministically and verify the contracts on etherscan using [Solidity 0.7.6](https://github.com/ethereum/solidity/releases/tag/v0.7.6) by default.

Expand Down Expand Up @@ -84,7 +84,7 @@ Note: Address will vary if contract code is changed or a different Solidity vers

Some networks require replay protection, making it incompatible with the default deployment process as it relies on a presigned transaction without replay protection (see https://github.com/Arachnid/deterministic-deployment-proxy).

Safe contracts use a different deterministic deployment proxy (https://github.com/safe-global/safe-singleton-factory). To make sure that the latest version of this package is installed, make sure to run `yarn add @gnosis.pm/safe-singleton-factory` before deployment. For more information, including how to deploy the factory to a new network, please refer to the factory repo.
Safe Smart Account contracts use a different deterministic deployment proxy (https://github.com/safe-global/safe-singleton-factory). To make sure that the latest version of this package is installed, run `yarn add -D @safe-global/safe-singleton-factory` before deployment. For more information, including deploying the factory to a new network, please refer to the factory repo.

Note: This will result in different addresses compared to hardhat's default deterministic deployment process.

Expand Down
120 changes: 120 additions & 0 deletions contracts/libraries/SafeMigration.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;

import {SafeStorage} from "../libraries/SafeStorage.sol";
import {Safe} from "../Safe.sol";

/**
* @title Migration Contract for Safe Upgrade
* @notice This is a generic contract that facilitates Safe and SafeL2 proxy contracts to migrate their singleton address.
* The supported target Safe version is immutable and set in the constructor during the deployment of the contract.
* This contract also supports migration with fallback handler update.
* @author @safe-global/safe-protocol
* @dev IMPORTANT: The library is intended to be used with the Safe standard proxy that stores the singleton address
* at the storage slot 0. Use at your own risk with custom proxy implementations. The contract will allow invocations
* to the migration functions only via delegatecall.
*/
contract SafeMigration is SafeStorage {
/**
* @notice Address of this contract
*/
address public immutable MIGRATION_SINGLETON;
/**
* @notice Address of the Safe Singleton implementation
*/
address public immutable SAFE_SINGLETON;
/**
* @notice Address of the Safe Singleton (L2) implementation
*/
address public immutable SAFE_L2_SINGLETON;
/**
* @notice Addresss of the Fallback Handler
*/
address public immutable SAFE_FALLBACK_HANDLER;

/**
* @notice Event indicating a change of a singleton address. Named master copy here for legacy reasons.
* @param singleton New master copy address
*/
event ChangedMasterCopy(address singleton);

/**
* @notice Modifier to make a function callable via delegatecall only.
* If the function is called via a regular call, it will revert.
*/
modifier onlyDelegateCall() {
require(address(this) != MIGRATION_SINGLETON, "Migration should only be called via delegatecall");
_;
}

/**
* @notice Constructor
* @param safeSingleton Address of the Safe Singleton implementation
* @param safeL2Singleton Address of the SafeL2 Singleton implementation
* @param fallbackHandler Address of the fallback handler implementation
*/
constructor(address safeSingleton, address safeL2Singleton, address fallbackHandler) {
MIGRATION_SINGLETON = address(this);

require(hasCode(safeSingleton), "Safe Singleton is not deployed");
require(hasCode(safeL2Singleton), "Safe Singleton (L2) is not deployed");
require(hasCode(fallbackHandler), "fallback handler is not deployed");

SAFE_SINGLETON = safeSingleton;
SAFE_L2_SINGLETON = safeL2Singleton;
SAFE_FALLBACK_HANDLER = fallbackHandler;
}

/**
* @notice Migrate the Safe contract to a new Safe Singleton implementation.
*/
function migrateSingleton() public onlyDelegateCall {
singleton = SAFE_SINGLETON;
emit ChangedMasterCopy(SAFE_SINGLETON);
}

/**
* @notice Migrate to Safe Singleton and set the fallback handler. This function is intended to be used when migrating
* a Safe to a version which also requires updating fallback handler.
*/
function migrateWithFallbackHandler() public onlyDelegateCall {
migrateSingleton();
Safe(payable(address(this))).setFallbackHandler(SAFE_FALLBACK_HANDLER);
}

/**
* @notice Migrate the Safe contract to a new Safe Singleton (L2) implementation.
*/
function migrateL2Singleton() public onlyDelegateCall {
singleton = SAFE_L2_SINGLETON;
emit ChangedMasterCopy(SAFE_L2_SINGLETON);
}

/**
* @notice Migrate to Safe Singleton (L2) and set the fallback handler. This function is intended to be used when migrating
* a Safe to a version which also requires updating fallback handler.
*/
function migrateL2WithFallbackHandler() public onlyDelegateCall {
migrateL2Singleton();
Safe(payable(address(this))).setFallbackHandler(SAFE_FALLBACK_HANDLER);
}

/**
* @notice Checks whether an account has code.
* @param account The address of the account to be checked.
* @return A boolean value indicating whether the address has code (true) or not (false).
* @dev This function relies on the `extcodesize` assembly opcode to determine whether an address has code.
* It does not reliably determine whether or not an address is a smart contract or an EOA.
*/
function hasCode(address account) internal view returns (bool) {
uint256 size;
/* solhint-disable no-inline-assembly */
/// @solidity memory-safe-assembly
assembly {
size := extcodesize(account)
}
/* solhint-enable no-inline-assembly */

return size > 0;
}
}
Loading
Loading