Thanks for the OpenZeppelin team for suggesting these improvements.
Context and scope
The sendAndCall interface allows accounts to bridge tokens and atomically use them in smart contract invocations on the destination chain. The current interface for receiving the bridged tokens is defined by receiveTokens does not allow for the receiving contract to authenticate the original sender of the call.
This level of authentication would be needed to, for example, send a message using an 3rd party messaging protocol. In this type of example, a Subnet could send a message to Ethereum by bridging tokens to the C-Chain using sendAndCall, and then using those tokens to pay for the messaging fee to send the message payload from the C-Chain to Ethereum. The contract on Ethereum would very likely need to authenticate who originally sent the message on the Subnet for many applications.
For this reason, the sourceBlockchainID and the originSenderAddress should be included in the SingleHopCallMessage message type, and the originSenderAddress should be included in the MultiHopCallMessage message type. These values should be passed through to the receiving contracts via the receiveTokens interface.
Discussion and alternatives
The multi-hop call case will need to be handled properly by identifying the original source/sender, and not the intermediate bridge contract. This roughly breaks down as follows:
TeleporterTokenSource
When sending a SingleHopCallMessage, sets the sourceBlockchainID as the local blockchain ID value, and the originSenderAddress as msg.sender.
When forwarding a MultiHopCallMessage to its final destination chain as a SingleHopCallMessage, sets the sourceBlockchainID as the blockchain ID that the Teleporter message is from.
When receiving a SingleHopCallMessage, checks that the sourceBlockchainID in the message payload matches that of the Teleporter message, and passes the sourceBlockchainID and originSenderAddress values in the message on to the target receiver
TeleporterTokenDestination
When sending a MultiHopCallMessage, sets the originSenderAddress as msg.sender.
When sending a SingleHopCallMessage, sets the sourceBlockchainID as the local blockchain ID value, and the originSenderAddress as msg.sender.
When receiving a SingleHopCallMessage, passes the sourceBlockchainID and originSenderAddress values in the message on to the target receiver
Open Question
What's the best way to encapsulate the sourceBlockchainID and originSenderAddress in the receiveTokens interface for both ERC20 and native token receivers? (i.e. wrapped in a struct or as individual params).
Thanks for the OpenZeppelin team for suggesting these improvements.
Context and scope The
sendAndCall
interface allows accounts to bridge tokens and atomically use them in smart contract invocations on the destination chain. The current interface for receiving the bridged tokens is defined byreceiveTokens
does not allow for the receiving contract to authenticate the original sender of the call.This level of authentication would be needed to, for example, send a message using an 3rd party messaging protocol. In this type of example, a Subnet could send a message to Ethereum by bridging tokens to the C-Chain using
sendAndCall
, and then using those tokens to pay for the messaging fee to send the message payload from the C-Chain to Ethereum. The contract on Ethereum would very likely need to authenticate who originally sent the message on the Subnet for many applications.For this reason, the
sourceBlockchainID
and theoriginSenderAddress
should be included in theSingleHopCallMessage
message type, and theoriginSenderAddress
should be included in theMultiHopCallMessage
message type. These values should be passed through to the receiving contracts via thereceiveTokens
interface.Discussion and alternatives The multi-hop call case will need to be handled properly by identifying the original source/sender, and not the intermediate bridge contract. This roughly breaks down as follows:
TeleporterTokenSource
SingleHopCallMessage
, sets thesourceBlockchainID
as the local blockchain ID value, and theoriginSenderAddress
asmsg.sender
.MultiHopCallMessage
to its final destination chain as aSingleHopCallMessage
, sets thesourceBlockchainID
as the blockchain ID that the Teleporter message is from.SingleHopCallMessage
, checks that thesourceBlockchainID
in the message payload matches that of the Teleporter message, and passes thesourceBlockchainID
andoriginSenderAddress
values in the message on to the target receiverTeleporterTokenDestination
MultiHopCallMessage
, sets theoriginSenderAddress
asmsg.sender
.SingleHopCallMessage
, sets thesourceBlockchainID
as the local blockchain ID value, and theoriginSenderAddress
asmsg.sender
.SingleHopCallMessage
, passes thesourceBlockchainID
andoriginSenderAddress
values in the message on to the target receiverOpen Question What's the best way to encapsulate the
sourceBlockchainID
andoriginSenderAddress
in thereceiveTokens
interface for both ERC20 and native token receivers? (i.e. wrapped in a struct or as individual params).