Skip to content

Commit

Permalink
feat: IndexingMath, Proxy, Migratable (#38)
Browse files Browse the repository at this point in the history
  • Loading branch information
deluca-mike authored Oct 30, 2024
1 parent f337029 commit c995528
Show file tree
Hide file tree
Showing 35 changed files with 313 additions and 39 deletions.
2 changes: 1 addition & 1 deletion src/ERC20Extended.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.26;
pragma solidity >=0.8.20 <0.9.0;

import { IERC20 } from "./interfaces/IERC20.sol";
import { IERC20Extended } from "./interfaces/IERC20Extended.sol";
Expand Down
2 changes: 1 addition & 1 deletion src/ERC3009.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.26;
pragma solidity >=0.8.20 <0.9.0;

import { IERC3009 } from "./interfaces/IERC3009.sol";

Expand Down
2 changes: 1 addition & 1 deletion src/ERC712Extended.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.26;
pragma solidity >=0.8.20 <0.9.0;

import { IERC712 } from "./interfaces/IERC712.sol";
import { IERC712Extended } from "./interfaces/IERC712Extended.sol";
Expand Down
61 changes: 61 additions & 0 deletions src/Migratable.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.8.20 <0.9.0;

import { IMigratable } from "./interfaces/IMigratable.sol";

/**
* @title Abstract implementation for exposing the ability to migrate a contract, extending ERC-1967.
* @author M^0 Labs
*/
abstract contract Migratable is IMigratable {
/* ============ Variables ============ */

/// @dev Storage slot with the address of the current factory. `keccak256('eip1967.proxy.implementation') - 1`.
uint256 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

/* ============ Interactive Functions ============ */

/// @inheritdoc IMigratable
function migrate() external {
_migrate(_getMigrator());
}

/* ============ View/Pure Functions ============ */

/// @inheritdoc IMigratable
function implementation() public view returns (address implementation_) {
assembly {
implementation_ := sload(_IMPLEMENTATION_SLOT)
}
}

/* ============ Internal Interactive Functions ============ */

/**
* @dev Performs an arbitrary migration by delegate-calling `migrator_`.
* @param migrator_ The address of a migrator contract.
*/
function _migrate(address migrator_) internal {
if (migrator_ == address(0)) revert ZeroMigrator();

if (migrator_.code.length == 0) revert InvalidMigrator();

address oldImplementation_ = implementation();

(bool success_, ) = migrator_.delegatecall("");
if (!success_) revert MigrationFailed();

address newImplementation_ = implementation();

emit Migrated(migrator_, oldImplementation_, newImplementation_);

// NOTE: Redundant event emitted to conform to the EIP-1967 standard.
emit Upgraded(newImplementation_);
}

/* ============ Internal View/Pure Functions ============ */

/// @dev Returns the address of a migrator contract.
function _getMigrator() internal view virtual returns (address);
}
48 changes: 48 additions & 0 deletions src/Proxy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.8.20 <0.9.0;

/**
* @title Minimal transparent proxy.
* @author M^0 Labs
*/
contract Proxy {
/// @dev Storage slot with the address of the current factory. `keccak256('eip1967.proxy.implementation') - 1`.
uint256 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

/**
* @dev Constructs the contract given the address of some implementation.
* @param implementation_ The address of some implementation.
*/
constructor(address implementation_) {
if (implementation_ == address(0)) revert();

assembly {
sstore(_IMPLEMENTATION_SLOT, implementation_)
}
}

fallback() external payable virtual {
bytes32 implementation_;

assembly {
implementation_ := sload(_IMPLEMENTATION_SLOT)
}

assembly {
calldatacopy(0, 0, calldatasize())

let result_ := delegatecall(gas(), implementation_, 0, calldatasize(), 0, 0)

returndatacopy(0, 0, returndatasize())

switch result_
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
}
2 changes: 1 addition & 1 deletion src/StatefulERC712.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.26;
pragma solidity >=0.8.20 <0.9.0;

import { IStatefulERC712 } from "./interfaces/IStatefulERC712.sol";

Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/IERC1271.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.26;
pragma solidity >=0.8.20 <0.9.0;

/**
* @title Standard Signature Validation Method for Contracts via EIP-1271.
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/IERC20.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.26;
pragma solidity >=0.8.20 <0.9.0;

/**
* @title ERC20 Token Standard.
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/IERC20Extended.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.26;
pragma solidity >=0.8.20 <0.9.0;

import { IERC20 } from "./IERC20.sol";
import { IERC3009 } from "./IERC3009.sol";
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/IERC3009.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.26;
pragma solidity >=0.8.20 <0.9.0;

import { IStatefulERC712 } from "./IStatefulERC712.sol";

Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/IERC712.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.26;
pragma solidity >=0.8.20 <0.9.0;

/**
* @title Typed structured data hashing and signing via EIP-712.
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/IERC712Extended.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.26;
pragma solidity >=0.8.20 <0.9.0;

import { IERC712 } from "./IERC712.sol";

Expand Down
44 changes: 44 additions & 0 deletions src/interfaces/IMigratable.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.8.20 <0.9.0;

/**
* @title Interface for exposing the ability to migrate a contract, extending the ERC-1967 interface.
* @author M^0 Labs
*/
interface IMigratable {
/* ============ Events ============ */

/**
* @notice Emitted when a migration to a new implementation is performed.
* @param migrator The address that performed the migration.
* @param oldImplementation The address of the old implementation.
* @param newImplementation The address of the new implementation.
*/
event Migrated(address indexed migrator, address indexed oldImplementation, address indexed newImplementation);

/**
* @notice Emitted when the implementation address for the proxy is changed.
* @param implementation The address of the new implementation for the proxy.
*/
event Upgraded(address indexed implementation);

/// @notice Emitted when calling `stopEarning` for an account approved as earner by the Registrar.
error InvalidMigrator();

/// @notice Emitted when the delegatecall to a migrator fails.
error MigrationFailed();

/// @notice Emitted when the zero address is passed as a migrator.
error ZeroMigrator();

/* ============ Interactive Functions ============ */

/// @notice Performs an arbitrarily defined migration.
function migrate() external;

/* ============ View/Pure Functions ============ */

/// @notice Returns the address of the current implementation contract.
function implementation() external view returns (address);
}
2 changes: 1 addition & 1 deletion src/interfaces/IStatefulERC712.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.26;
pragma solidity >=0.8.20 <0.9.0;

import { IERC712Extended } from "./IERC712Extended.sol";

Expand Down
2 changes: 1 addition & 1 deletion src/libs/Bytes32String.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.26;
pragma solidity >=0.8.20 <0.9.0;

/**
* @title A library to convert between string and bytes32 (assuming 32 characters or less).
Expand Down
42 changes: 33 additions & 9 deletions src/libs/ContractHelper.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.26;
pragma solidity >=0.8.20 <0.9.0;

// solhint-disable max-line-length

Expand Down Expand Up @@ -35,14 +35,38 @@ library ContractHelper {
nonce_ == 0x00
? abi.encodePacked(bytes1(0xd6), bytes1(0x94), account_, bytes1(0x80))
: nonce_ <= 0x7f
? abi.encodePacked(bytes1(0xd6), bytes1(0x94), account_, uint8(nonce_))
: nonce_ <= 0xff
? abi.encodePacked(bytes1(0xd7), bytes1(0x94), account_, bytes1(0x81), uint8(nonce_))
: nonce_ <= 0xffff
? abi.encodePacked(bytes1(0xd8), bytes1(0x94), account_, bytes1(0x82), uint16(nonce_))
: nonce_ <= 0xffffff
? abi.encodePacked(bytes1(0xd9), bytes1(0x94), account_, bytes1(0x83), uint24(nonce_))
: abi.encodePacked(bytes1(0xda), bytes1(0x94), account_, bytes1(0x84), uint32(nonce_))
? abi.encodePacked(bytes1(0xd6), bytes1(0x94), account_, uint8(nonce_))
: nonce_ <= 0xff
? abi.encodePacked(
bytes1(0xd7),
bytes1(0x94),
account_,
bytes1(0x81),
uint8(nonce_)
)
: nonce_ <= 0xffff
? abi.encodePacked(
bytes1(0xd8),
bytes1(0x94),
account_,
bytes1(0x82),
uint16(nonce_)
)
: nonce_ <= 0xffffff
? abi.encodePacked(
bytes1(0xd9),
bytes1(0x94),
account_,
bytes1(0x83),
uint24(nonce_)
)
: abi.encodePacked(
bytes1(0xda),
bytes1(0x94),
account_,
bytes1(0x84),
uint32(nonce_)
)
)
)
)
Expand Down
Loading

0 comments on commit c995528

Please sign in to comment.