Skip to content

Commit

Permalink
Add ERC20Bridgeable: An ERC-7802 implementation (#27)
Browse files Browse the repository at this point in the history
* cross-chain prototype v1

* split common <> axelar

* add relay observability

* Update oz to master

* Iterate

* Remove salt

* Iterate

* Add GatewayAxelar specialization

* Iterate

* Fix GatewayAxelarSource

* Remove unnecessary contract

* Iteration

* Remove interfaces

* Checkpoint

* Add incoming dual mode

* Fix compilation

* Apply review suggestions

* Install axelar contracts

* Apply review sugggestion

* Apply suggestions

* wip fixes

* trying to get crosschain to compile

* fix compilation

* minor update

* make attributes a bytes[]

* Address comments and add some tests

* refactor and test caip utils

* up

* using unmerged version of Strings with parsing

* up

* workflow testing (active and passive)

* update

* up

* address PR comments

* renovate

* rename

* fix foundry

* codespell

* use checksumed addresses

* use @openzepplin/contracts@master

* add/move files that are no longer planned to be in the main repo

* get submodules when running tests

* Apply suggestions from code review

* Apply suggestions from code review

Co-authored-by: Francisco Giordano <[email protected]>

* simplify

* update

* validateReceivedMessage -> setExecutedMessage

* Add docs

* Update AxelarGatewayDestination.sol

Co-authored-by: Francisco Giordano <[email protected]>

* Update

* Update

* Updated ERC specs

* executeMessage returns bytes4

* Add AxelarGatewayDuplex

* remove npm contracts dependency in favor of the master submodule

* slither remappings

* clarify CAIP-10 format

* document reverts

* unused imports

* unexpected attributes too short

* document remoteGateway format

* clarify AxelarGatewayDestination._execute

* rewrite require(..., error); as if (...) revert error;

* typography

* custom errors

* replace require with string with custom error

* Apply audit review suggestions

* Adjust checks.yml

* Pick CI changes

* Point gitmodules to master on OZ contracts

* lint

* Fix CI

* Fix CI 2

* Fix slither

* up

* up

* Disable locked-ether slither rule for duplex

* Make prettier version consistent

* Run `forge update`

* Sync prettier version with vanilla contracts

* Point .gitmodules to master

* ERC7802 with ERC7786 gateway

* Offload logic from token

* Change approach

* Rename

* Update NatSpec

* Simplified

* Simplify more

* Simplify more

* up

* up

* up

* up

* Add tests

* Test ERC165 in ERC20Bridgeable

* Update draft-ERC20Bridgeable.sol

* simplify mock

* cleanup

* Downgrade to Solidity 0.8.20 in IERC7802 and ERC20Bridgeable

* shouldSupportInterfaces update

* remapping to the helpers in lib/@openzeppelin-contracts/test

* change dependency

* move interface

* skip foundry install

* checkout recurcive

* Update contracts/token/ERC20/extensions/draft-ERC20Bridgeable.sol

Co-authored-by: Francisco Giordano <[email protected]>

* re-add test:inheritance

* fix inheritance ordering

---------

Co-authored-by: Hadrien Croubois <[email protected]>
Co-authored-by: Ernesto García <[email protected]>
Co-authored-by: Francisco Giordano <[email protected]>
  • Loading branch information
4 people authored Dec 13, 2024
1 parent fbcc07c commit e6c66b6
Show file tree
Hide file tree
Showing 12 changed files with 7,855 additions and 3,588 deletions.
3 changes: 0 additions & 3 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,3 @@ runs:
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly
- name: Install submodule dependencies
shell: bash
run: forge install
8 changes: 8 additions & 0 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ jobs:
GAS: true
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up environment
uses: ./.github/actions/setup
- name: Run tests and generate gas report
Expand All @@ -44,6 +46,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up environment
uses: ./.github/actions/setup
- name: Run coverage
Expand All @@ -53,6 +57,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up environment
uses: ./.github/actions/setup
- name: Run tests
Expand All @@ -62,6 +68,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up environment
uses: ./.github/actions/setup
- uses: crytic/[email protected]
Expand Down
27 changes: 27 additions & 0 deletions contracts/mocks/token/draft-ERC20BridgeableMock.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import {ERC20, ERC20Bridgeable} from "../../token/ERC20/extensions/draft-ERC20Bridgeable.sol";

abstract contract ERC20BridgeableMock is ERC20Bridgeable {
address bridge;

error OnlyTokenBridge();

event OnlyTokenBridgeFnCalled(address caller);

constructor(address bridge_) {
bridge = bridge_;
}

function onlyTokenBridgeFn() external onlyTokenBridge {
emit OnlyTokenBridgeFnCalled(msg.sender);
}

function _checkTokenBridge(address sender) internal view override {
if (sender != bridge) {
revert OnlyTokenBridge();
}
}
}
51 changes: 51 additions & 0 deletions contracts/token/ERC20/extensions/draft-ERC20Bridgeable.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {IERC7802} from "./draft-IERC7802.sol";
import {ERC165, IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";

/**
* @dev ERC20 extension that implements the standard token interface according to
* https://github.com/ethereum/ERCs/blob/bcea9feb6c3f3ded391e33690056635d722b101e/ERCS/erc-7802.md[ERC-7802].
*
* NOTE: To implement a crosschain gateway for a chain, consider using an implementation if {IERC7786} token
* bridge (e.g. {AxelarGatewaySource}, {AxelarGatewayDestination}).
*/
abstract contract ERC20Bridgeable is ERC20, ERC165, IERC7802 {
/// @dev Modifier to restrict access to the token bridge.
modifier onlyTokenBridge() {
_checkTokenBridge(msg.sender);
_;
}

/// @inheritdoc ERC165
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return interfaceId == type(IERC7802).interfaceId || super.supportsInterface(interfaceId);
}

/**
* @dev See {IERC7802-crosschainMint}. Emits a {CrosschainMint} event.
*/
function crosschainMint(address to, uint256 value) public virtual override onlyTokenBridge {
_mint(to, value);
emit CrosschainMint(to, value, msg.sender);
}

/**
* @dev See {IERC7802-crosschainBurn}. Emits a {CrosschainBurn} event.
*/
function crosschainBurn(address from, uint256 value) public virtual override onlyTokenBridge {
_burn(from, value);
emit CrosschainBurn(from, value, msg.sender);
}

/**
* @dev Checks if the caller is a trusted token bridge. MUST revert otherwise.
*
* Developers should implement this function using an access control mechanism that allows
* customizing the list of allowed senders. Consider using {AccessControl} or {AccessManaged}.
*/
function _checkTokenBridge(address caller) internal virtual;
}
30 changes: 30 additions & 0 deletions contracts/token/ERC20/extensions/draft-IERC7802.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";

/// @title IERC7802
/// @notice Defines the interface for crosschain ERC20 transfers.
interface IERC7802 is IERC165 {
/// @notice Emitted when a crosschain transfer mints tokens.
/// @param to Address of the account tokens are being minted for.
/// @param amount Amount of tokens minted.
/// @param sender Address of the caller (msg.sender) who invoked crosschainMint.
event CrosschainMint(address indexed to, uint256 amount, address indexed sender);

/// @notice Emitted when a crosschain transfer burns tokens.
/// @param from Address of the account tokens are being burned from.
/// @param amount Amount of tokens burned.
/// @param sender Address of the caller (msg.sender) who invoked crosschainBurn.
event CrosschainBurn(address indexed from, uint256 amount, address indexed sender);

/// @notice Mint tokens through a crosschain transfer.
/// @param _to Address to mint tokens to.
/// @param _amount Amount of tokens to mint.
function crosschainMint(address _to, uint256 _amount) external;

/// @notice Burn tokens through a crosschain transfer.
/// @param _from Address to burn tokens from.
/// @param _amount Amount of tokens to burn.
function crosschainBurn(address _from, uint256 _amount) external;
}
Loading

0 comments on commit e6c66b6

Please sign in to comment.