forked from paradigmxyz/reth
-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #28 from taikoxyz/modify_erc20_xchain_version_inhe…
…ritance feat(gwyneth): Modify `xChainToken` inheritance
- Loading branch information
Showing
7 changed files
with
222 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,8 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | ||
import "../gwyneth/XChainToken.sol"; | ||
import "../gwyneth/XChainERC20Token.sol"; | ||
|
||
contract xErc20Example is ERC20, XChainToken { | ||
constructor() ERC20("xERC20", "xERC") { | ||
_mint(msg.sender, 100_000_000_000 * 10**18 ); | ||
} | ||
contract xERC20Example is XChainERC20Token { | ||
constructor(string memory name_, string memory symbol_, address premintAddress_, uint256 premintAmount_ ) XChainERC20Token(name_, symbol_, premintAddress_, premintAmount_ ) {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
167 changes: 167 additions & 0 deletions
167
packages/protocol/contracts/gwyneth/XChainERC20Token.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity >=0.8.12 <0.9.0; | ||
|
||
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | ||
import "./XChain.sol"; | ||
|
||
// The reason we need this is because i realized we need to somehow 'override' some of the functions we have in ERC20, and since the balances need to be affected in ERC20 and XChainToken, it is not possible with the current standard, except if we linearize the inheritance (ERC20 -> XChainToken -> TokenImplementation) | ||
contract XChainERC20Token is XChain, ERC20 { | ||
// Only stored on L1 | ||
// @Brecht -> Shall we overwrite in our xERC20Example the totalSupply() of ERC20 ? And use this var instead of the ERC20's _totalSupply | ||
// Not sure in this because i guess it shall serve the same purpose as totalSupply(), also it is a completely different interaction (on xChain) than on the canonical chain, but the totalSupply shall be the same IMO. | ||
//meeting meinutes: We can get rid of this. | ||
uint private _totalBalance; | ||
// Stored on all chains | ||
// This lead me to realize we need thi sinheritance: | ||
// Somehow this has to overwrite (or rather be used) in the ERC20 contract, right ? Like with the balanceOf(addr), otherwise the erc20 is not 'notified'. | ||
// What if we have a function in child ERC20.. which needs to be implemented, like modifyERC20Balance(); | ||
// Example: | ||
// BOb does an xTransfer to Alice from cahin A to chain B. It is is OK but it shall translate into an ERC20 balance change too, not only in this contract but in the ERC20 contract which is with the prev. inheritance was not possible. | ||
/*New variables - overriden from ERC20 since we want them to be modifiable*/ | ||
mapping(address => uint) private _balances; // -> Need to redefine and override functions | ||
uint256 private _totalSupply; // -> Need to redefine and override functions | ||
|
||
constructor(string memory name_, string memory symbol_, address premintAddress_, uint256 premintAmount_ ) ERC20(name_, symbol_) { | ||
_mint(premintAddress_, premintAmount_); | ||
} | ||
|
||
// xtransfer for async case (proof needed) | ||
function xtransfer(address to, uint amount, uint256 fromChainId, uint256 toChainId, bytes calldata proof) | ||
xFunction(fromChainId, toChainId, proof) | ||
external | ||
{ | ||
if (EVM.chainId() == fromChainId) { | ||
_balances[msg.sender] -= amount; | ||
} | ||
if (EVM.chainId() == toChainId) { | ||
_balances[to] += amount; | ||
} | ||
} | ||
|
||
// xtransfer for async case | ||
function xtransfer(address to, uint amount, uint256 fromChainId, uint256 toChainId) | ||
external | ||
{ | ||
require(EVM.chainId() == fromChainId, "ASYNC_CASE, only call it on source chain"); | ||
|
||
_balances[msg.sender] -= amount; | ||
// We need to do xCallOptions (incoprpotate the minting on the dest chain) | ||
// We chack we are on the corect sourvce chain and then we do evm. | ||
EVM.xCallOptions(toChainId); | ||
this.xmint(to, amount); | ||
} | ||
|
||
// DO a mind-puzzle with Brecht if this is really solving the problems of Alice sending Bob from chainA to chainB some tokens!! | ||
// Mint function -> Should only be called by the SC itself. | ||
function xmint(address to, uint amount) | ||
external | ||
{ | ||
// Only be called by itself (internal bookikeeping) | ||
require(msg.sender == address(this), "NOT_ALLOWED"); | ||
_balances[to] += amount; | ||
} | ||
|
||
/* Overrides of ERC20 */ | ||
//Change totalSupply and apply xExecuteOn modifier | ||
function totalSupply() //Is it the same as totalSupply() if so, i think that shall be fine! | ||
xExecuteOn(EVM.l1ChainId) //why it has an xExecuteOn modifier ? And why it is applied only here ? | ||
public | ||
view | ||
override | ||
returns (uint256) | ||
{ | ||
return _totalSupply; | ||
} | ||
|
||
function balanceOf(address account) public view virtual override returns (uint256) { | ||
return _balances[account]; | ||
} | ||
|
||
/** | ||
* @dev Moves `amount` of tokens from `from` to `to`. | ||
* | ||
* This internal function is equivalent to {transfer}, and can be used to | ||
* e.g. implement automatic token fees, slashing mechanisms, etc. | ||
* | ||
* Emits a {Transfer} event. | ||
* | ||
* Requirements: | ||
* | ||
* - `from` cannot be the zero address. | ||
* - `to` cannot be the zero address. | ||
* - `from` must have a balance of at least `amount`. | ||
*/ | ||
function _transfer(address from, address to, uint256 amount) internal virtual override { | ||
require(from != address(0), "ERC20: transfer from the zero address"); | ||
require(to != address(0), "ERC20: transfer to the zero address"); | ||
|
||
_beforeTokenTransfer(from, to, amount); | ||
|
||
uint256 fromBalance = _balances[from]; | ||
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); | ||
unchecked { | ||
_balances[from] = fromBalance - amount; | ||
// Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by | ||
// decrementing then incrementing. | ||
_balances[to] += amount; | ||
} | ||
|
||
emit Transfer(from, to, amount); | ||
|
||
_afterTokenTransfer(from, to, amount); | ||
} | ||
|
||
/** @dev Creates `amount` tokens and assigns them to `account`, increasing | ||
* the total supply. | ||
* | ||
* Emits a {Transfer} event with `from` set to the zero address. | ||
* | ||
* Requirements: | ||
* | ||
* - `account` cannot be the zero address. | ||
*/ | ||
function _mint(address account, uint256 amount) internal virtual override { | ||
require(account != address(0), "ERC20: mint to the zero address"); | ||
|
||
_beforeTokenTransfer(address(0), account, amount); | ||
|
||
_totalSupply += amount; | ||
unchecked { | ||
// Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. | ||
_balances[account] += amount; | ||
} | ||
emit Transfer(address(0), account, amount); | ||
|
||
_afterTokenTransfer(address(0), account, amount); | ||
} | ||
|
||
/** | ||
* @dev Destroys `amount` tokens from `account`, reducing the | ||
* total supply. | ||
* | ||
* Emits a {Transfer} event with `to` set to the zero address. | ||
* | ||
* Requirements: | ||
* | ||
* - `account` cannot be the zero address. | ||
* - `account` must have at least `amount` tokens. | ||
*/ | ||
function _burn(address account, uint256 amount) internal virtual override { | ||
require(account != address(0), "ERC20: burn from the zero address"); | ||
|
||
_beforeTokenTransfer(account, address(0), amount); | ||
|
||
uint256 accountBalance = _balances[account]; | ||
require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); | ||
unchecked { | ||
_balances[account] = accountBalance - amount; | ||
// Overflow not possible: amount <= accountBalance <= totalSupply. | ||
_totalSupply -= amount; | ||
} | ||
|
||
emit Transfer(account, address(0), amount); | ||
|
||
_afterTokenTransfer(account, address(0), amount); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
35 changes: 35 additions & 0 deletions
35
packages/protocol/scripts/L2_txn_simulation/CreateXChainTxn.s.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// SPDX-License-Identifier: MIT | ||
// _____ _ _ _ _ | ||
// |_ _|_ _(_) |_____ | | __ _| |__ ___ | ||
// | |/ _` | | / / _ \ | |__/ _` | '_ (_-< | ||
// |_|\__,_|_|_\_\___/ |____\__,_|_.__/__/ | ||
|
||
pragma solidity ^0.8.20; | ||
|
||
import "forge-std/Script.sol"; | ||
import "forge-std/console2.sol"; | ||
|
||
import "../../contracts/examples/xERC20Example.sol"; | ||
|
||
contract CreateXChainTxn is Script { | ||
address public Bob_deployer_and_xchain_sender = 0x8943545177806ED17B9F23F0a21ee5948eCaa776; //Also .env PRIV_KEY is tied to Bob | ||
address public Alice_xchain_receiver = 0xE25583099BA105D9ec0A67f5Ae86D90e50036425; | ||
|
||
function run() external { | ||
vm.startBroadcast(); | ||
|
||
//Deploy a contract and mints 100k for Bob | ||
xERC20Example exampleXChainToken = new xERC20Example("xChainExample", "xCE", Bob_deployer_and_xchain_sender, 100_000 * 1e18); | ||
|
||
// ChainId to send to | ||
uint256 dummyChainId = 12346; // Does not matter at this point | ||
|
||
console2.log("Sender balance (before sending):", exampleXChainToken.balanceOf(Bob_deployer_and_xchain_sender)); | ||
exampleXChainToken.xtransfer(Alice_xchain_receiver, 2 * 1e18, block.chainid, dummyChainId); | ||
|
||
console2.log("Sender balance:", exampleXChainToken.balanceOf(Bob_deployer_and_xchain_sender)); | ||
console2.log("Receiver balance:", exampleXChainToken.balanceOf(Alice_xchain_receiver)); | ||
|
||
vm.stopBroadcast(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters