Last active
July 6, 2021 06:43
-
-
Save itzmeanjan/02b18ed506c5fb0788992009308a3c5f to your computer and use it in GitHub Desktop.
An illustration of sending data from Ethereum root chain to Matic child chain
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
// File: contracts/child/ChildToken/ChildERC20.sol | |
pragma solidity 0.6.6; | |
contract ChildERC20 is | |
ERC20, | |
IChildToken, | |
AccessControlMixin, | |
NativeMetaTransaction, | |
ChainConstants, | |
ContextMixin | |
{ | |
bytes32 public constant DEPOSITOR_ROLE = keccak256("DEPOSITOR_ROLE"); | |
constructor( | |
string memory name_, | |
string memory symbol_, | |
uint8 decimals_, | |
address childChainManager | |
) public ERC20(name_, symbol_) { | |
_setupContractId("ChildERC20"); | |
_setupDecimals(decimals_); | |
_setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); | |
_setupRole(DEPOSITOR_ROLE, childChainManager); | |
_initializeEIP712(name_, ERC712_VERSION); | |
} | |
// This is to support Native meta transactions | |
// never use msg.sender directly, use _msgSender() instead | |
function _msgSender() | |
internal | |
override | |
view | |
returns (address payable sender) | |
{ | |
return ContextMixin.msgSender(); | |
} | |
/** | |
* @notice called when token is deposited on root chain | |
* @dev Should be callable only by ChildChainManager | |
* Should handle deposit by minting the required amount for user | |
* Make sure minting is done only by this function | |
* @param user user address for whom deposit is being done | |
* @param depositData abi encoded amount | |
*/ | |
function deposit(address user, bytes calldata depositData) | |
external | |
override | |
only(DEPOSITOR_ROLE) | |
{ | |
uint256 amount = abi.decode(depositData, (uint256)); | |
// tokens minted on child chain for `user` | |
_mint(user, amount); | |
// this is not the only way of doing it, using low level call here | |
// this might be little overengineering for this given scenario | |
(bool success, bytes memory result) = address(this).call(abi.encodeWithSignature("callback(address,uint256)", user, amount)); | |
// or as we know function to be called in this contract, we can do another thing | |
// given `callback` function is predefined for child chain contract | |
// where we can also emit some event which can be caught, offchain | |
callback(user, amount); | |
} | |
function callback(address user, uint256 amount) internal { | |
// doing nothing useful here, as of now | |
// but you can always implement custom logic here, which is to be executed | |
// whenever any token deposit is performed from root to child | |
} | |
/** | |
* @notice called when user wants to withdraw tokens back to root chain | |
* @dev Should burn user's tokens. This transaction will be verified when exiting on root chain | |
* @param amount amount of tokens to withdraw | |
*/ | |
function withdraw(uint256 amount) external { | |
_burn(_msgSender(), amount); | |
} | |
} |
@itzmeanjan is it onStateReceived
or onStateReceive
(without d) or both works? because I have seen few contracts on matic-pos-portal with the latter one
What is the use of that function _msgSender() in line 30??
Can someone please explain the working of that function??
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just token amount & deposit for address
Please check
deposit
method implementation forChildERC20.sol
.This can facilitate calling some callback function in same contract i.e. child token on Matic, which can be done any of following two ways
address(this).call(...)
: which might be little overkill given this scenario.More Data
Or if you want to send some more data from main chain contract to child chain, you do following
depositFor
in RootChainManagerStateSender.syncState
, deployed at 0x...StateSender.syncState
| this, but this time make sure, you're passing proper target contract address on child chain i.e. Matic, which will be invoked by our chain syncer's internally, so make sure you don't use any kind of event emission there. We call this kind of function callssystem-calls
, because they get called by our heimdal layer state syncer nodes.StateSynced
event, that are tracked by our heimdal layer nodes.abi.decode
. Now you can do what you want to do with this synced message from Ethreum to Matic.But wait, how does the heimdal layer state syncer get to know which function on target contract to be specified ?
Yes, we need to implement this interface, where
onStateReceived
must be implemented.So heimdal layer syncer will call this function on address specified in
syncState(address receiver, bytes calldata data)
, which you called on root chain.Now in your child contract, in
onStateReceived
you can put custom logic. Take some inspiration fromChildChainManager
.Now it's upto you what you do with synced data, which you just sent form Ethereum to Matic.
Was I clear ?
Let me know 😉